// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
define(['hp/core/Localizer', 'jquery'], function (localizer) {
"use strict";

    var IndexTime = (function () {
      
        var MILLISECONDS_PER_YEAR = (1000 * 60 * 60 * 24 * 365); // close enough
        var MILLISECONDS_PER_DAY = (1000 * 60 * 60 * 24);
        var MILLISECONDS_PER_HOUR = (1000 * 60 * 60);
        var MILLISECONDS_PER_MINUTE = (1000 * 60);
        
        var PATTERN_DELTAS = {
            'core.duration.y': MILLISECONDS_PER_YEAR,
            'core.duration.d': MILLISECONDS_PER_DAY,
            'core.duration.h': MILLISECONDS_PER_HOUR,
            'core.duration.m': MILLISECONDS_PER_MINUTE
        };
        
        var DATE_RANGE_REGEXP =
            new RegExp('\\[\\d{4}-\\d{2}-\\d{2} TO \\d{4}-\\d{2}-\\d{2}\\]');
        
        /**
         * arg is either a location or an IndexFilter to start from
         */
        function IndexTime() {
            
            var patterns; // lazily build
            
            function generatePatterns() {
                var regexp;
                patterns = [];
                $.each(PATTERN_DELTAS, function (pattern, delta) {
                    regexp = new RegExp('^' + localizer.getString(pattern, ['(\\d+)']) + '$');
                    patterns.push({regexp: regexp, delta: delta});
                });
            }
            
            /**
             * @public
             * Converts the relative value to an absolute time relative
             * to the current time.
             */
            function convertDelta(deltaString) {
                var length, pattern, matches, result, now = new Date();
                if (! patterns) {
                    generatePatterns();
                }
                length = patterns.length;
                for (var i=0; i<length; i++) {
                    pattern = patterns[i];
                    matches = pattern.regexp.exec(deltaString);
                    if (matches) {
                        result = new Date(now.getTime() -
                            (matches[1] + pattern.delta)).toISOString();
                        break;
                    }
                }
                return result;
            }
            
            function beginningOfToday() {
                var result = new Date();
                result.setHours(0, 0, 0, 0);
                return result.toISOString();
            }
            
            function parseDate(date) {
                // convert 'yyyy-mm-dd' to Date object
                return new Date(
                    parseInt(date.slice(0,4), 10),
                    parseInt(date.slice(5,7), 10) - 1,
                    parseInt(date.slice(8,10), 10));
            }
            
            this.toRESTFilters = function (property, value, filters) {
                var reference, fromDate, toDate;
                if ('<' === value[0]) {
                    reference = convertDelta(value.substring(1));
                    filters.push('"' + property + ' > ' + reference + '"');
                } else if ('>' === value[0]) {
                    reference = convertDelta(value.substring(1));
                    // operator is opposite because '>5d' means
                    // "timestamp less than 5 days ago"
                    filters.push('"' + property + ' < ' + reference + '"');
                } else if (localizer.getString('core.duration.today').toLowerCase()
                    === value.toLowerCase()) {
                    filters.push('"' + property + ' > ' + beginningOfToday() + '"');
                } else if (DATE_RANGE_REGEXP.test(value)) {
                    // convert from [yyyy-mm-dd TO yyyy-mm-dd] to REST syntax
                    fromDate = parseDate(value.slice(1,11));
                    toDate = parseDate(value.slice(15,25));
                    toDate.setHours(23, 59, 59, 999);
                    filters.push('"' + property + ' > ' + fromDate.toISOString() + '"');
                    filters.push('"' + property + ' < ' + toDate.toISOString() + '"');
                }
            };
        }

        return new IndexTime();
    }());

    return IndexTime;
});
