Figment.Import('Figment.Date',Figment.getJSRoot() + '_framework');
Figment.Import('Figment.EventHandler',Figment.getJSRoot() + '_framework');
Figment.Import('Figment.HashTable',Figment.getJSRoot() + '_framework');

Figment.Namespace('Disney.WDPRO.IBC.Dates');

Disney.WDPRO.IBC.Dates = {
    paths: new Figment.HashTable(),

    calculateLOS: function(from,to)
    {
        var fromTimeInMillis = from.getTime(),
            toTimeInMillis = to.getTime(),
            millisPerDay = parseInt('0x5265c00L', 16);

        //return ((toTimeInMillis - fromTimeInMillis) / millisPerDay);
        // Added Math.round to account for times when there is an extra/one less hour in one day
        // of a date range (Daylight Savings)
        return Math.round(((toTimeInMillis - fromTimeInMillis) / millisPerDay));
    },

    isValidRange: function(start,end,pathType)
    {
        var rule = Disney.WDPRO.IBC.Dates.paths.get(pathType);
        var result;
        var minDate,maxDate;

        if( rule !== null )
        {
            result = Disney.WDPRO.IBC.Dates.containsBlockOutDays(start,end,pathType);
            if( !result )
            {
                minDate = rule.getMinDate();
                maxDate = rule.getMaxDate();
                result = Figment.Date.between(start,minDate,maxDate);
                if( result )
                {
                    result = Figment.Date.between(end,minDate,maxDate);
                }
            }
        }
        // Force cleanup
        delete rule;
        delete minDate;
        delete maxDate;

        return result;
    },

    isValid: function(date,pathType)
    {
        var rule = Disney.WDPRO.IBC.Dates.paths.get(pathType);
        var result;
        var minDate,maxDate;

        if( rule !== null )
        {
            if( !result )
            {
                minDate = rule.getMinDate();
                maxDate = rule.getMaxDate();
                result = Figment.Date.between(date,minDate,maxDate);
            }
        }
        // Force cleanup
        delete rule;
        delete minDate;
        delete maxDate;

        return result;
    },


    // This doesn't reset the default arrival date it actually returns the
    // Time used to reset the default arrival value of an element
    resetDefaultArrivalDate: function (pathType)
    {
        var rule = Disney.WDPRO.IBC.Dates.paths.get(pathType);

        if ( rule !== null )
        {
            var minArrival = rule.getMinDate();

            if ( minArrival !== null )
            {
                return ( minArrival.getTime() );
            }
        }
        return null;
    },

    // This returns a valid departure date.  A valid departure date is a date
    // that is between the min LOS and max LOS (inclusive) after the arrival
    // date.  If the LOS is a less than the min LOS, then reset the LOS to the
    // default LOS for the path type.  If the LOS is greater than the max LOS,
    // then constrain the LOS to the max LOS value.
    resetDay: function(arrivalDate, departureDate, pathType) {
        var los = Disney.WDPRO.IBC.Dates.calculateLOS(arrivalDate,departureDate);
        var rule = Disney.WDPRO.IBC.Dates.paths.get(pathType);
        // If the date is valid, then we never have a reason to adjust the days of the date
        var daysToAdjustDepartureDateBy = 0;

        if( rule !== null ) {
            if( los > rule.getMaxLOS() ) {
                daysToAdjustDepartureDateBy = rule.getMaxLOS();
            } else if( los < rule.getMinLOS() ) {
                daysToAdjustDepartureDateBy = rule.getDefaultLOS();
            }


            if(daysToAdjustDepartureDateBy > 0) {
                // Make a new instance so that we don't hose arrivalDate
                departureDate = new Date(arrivalDate);
                departureDate.setDate(departureDate.getDate() + daysToAdjustDepartureDateBy);
            }
        }
        return departureDate;
    },

    // Get the default departure date by adding the default length of stay
    // to the arrival date function parameter for the given path type
    resetDefaultDepartureDate: function(arrivalDate, pathType) {
        var rule = Disney.WDPRO.IBC.Dates.paths.get(pathType);
        if ( rule !== null ) {
            if (rule.getDefaultLOS() !== null) {
                var departureDate = new Date(arrivalDate);
                departureDate.setDate(departureDate.getDate() + rule.getDefaultLOS());
                return departureDate;
            }
        }
        return null;
    },

    containsBlockOutDays: function(start,end,pathType)
    {
        var rule = Disney.WDPRO.IBC.Dates.paths.get(pathType);
        var result = false;
        var blockOutDays;
        var i;
        var blockOutDay;

        if( rule !== null )
        {
            blockOutDays = rule.getBlockOutDates();
            if( blockOutDays !== null )
            {
                for( i=0; i < blockOutDays.length; i++ )
                {
                    blockOutDay = blockOutDays[i];
                    if( Figment.Date.between(blockOutDay,start,end) )
                    {
                        result = true;
                        break;
                    }
                }
            }
        }
        // Force cleanup
        delete rule;
        delete blockOutDay;
        delete blockOutDays;

        return result;
    },

    addPathRules: function(pathType,rule)
    {
        Disney.WDPRO.IBC.Dates.paths.put(pathType,rule);
    },

    cleanup: function(evt)
    {
        delete Disney.WDPRO.IBC.Dates.paths;
    }
};

Disney.WDPRO.IBC.Dates.Rule = Figment.Class();
Disney.WDPRO.IBC.Dates.Rule.prototype = {
    initialize: function(minDate,maxDate,minLOS,maxLOS,defaultLOS)
    {
        this.minDate                = minDate;
        this.maxDate                = maxDate;
        this.minLOS                 = minLOS;
        this.maxLOS                 = maxLOS;
        this.defaultLOS             = defaultLOS;
        this.blockoutDays           = [];
    },

    getMinDate: function()
    {
        return this.minDate;
    },

    getMaxDate: function()
    {
        return this.maxDate;
    },

    getMinLOS: function()
    {
        return this.minLOS;
    },

    getMaxLOS: function()
    {
        return this.maxLOS;
    },

    getDefaultLOS: function ()
    {
        return this.defaultLOS;
    },

    getBlockOutDates: function()
    {
        return this.blockoutDays;
    },

    addBlockOutDate: function(date)
    {
        this.blockoutDays.push(date);
    },

    addBlockOutDates: function(start,end)
    {
        var los = Disney.WDPRO.IBC.Dates.calculateLOS(start,end);
        var i;

        for( i=0; i < los.length; i++ )
        {
            // Add the number of days to the start date
            this.blockoutDays.push(Figment.Date.add(start,'D',i));
        }
    }
};

// Cleanup after ourselves (being nice to IE users)
Figment.EventHandler.addEvent(document,'unload',Disney.WDPRO.IBC.Dates.cleanup);

