(function() {
    var Ext = window.Ext4 || window.Ext;

    /**
     * @private
     * Provides the functionality for calculating an artifacts health as represented by a color.
     * A simple example:
     *
     *     @example
     *     var colorObject = Rally.util.HealthColorCalculator.getHealthColor({
     *         startDate: new Date(2000, 2, 2),
     *         endDate: new Date(2000, 3, 3),
     *         asOfDate: new Date(2010, 2, 5),
     *         percentComplete: 0.50
     *     });
     *     alert(colorObject.hex);
     *
     */
    Ext.define('Rally.util.HealthColorCalculator', {
        requires: [],

        singleton: true,

        colors:{
            red:{
                label: 'Late',
                hex: '#F66349'
            },
            green:{
                label: 'On Track',
                hex: '#8DC63F'
            },
            yellow:{
                label: 'At Risk',
                hex: '#FAD200'
            },
            white:{
                label: 'Not Started',
                hex: '#E0E0E0'
            },
            gray:{
                label: 'Complete',
                hex: '#D1D1D1'
            }
        },

        /**
         * @param {Object} config
         * @param {Date}  config.startDate  (days since the epoch or date type where Tomorrow()-Today() = 1.0 (real))
         * @param {Date} config.endDate (same type as startDate)
         * @param {Date} config.asOfDate (same type as startDate) - Most often today. The naming of
         * this variable supports the idea that you may want to look
         * at the report as-of a certain date. All A2.0 reports will
         * support printing any report as-of a certain timestamp.
         * @param {Number} config.acceptanceStartDelay Defaults to 0.1 * (endDate - startDate)
         * @param {Number} config.warningDelay Defaults to 0.1 * (endDate - startDate)
         * @param {Boolean} config.inProgress Defaults to percentComplete > 0
         * @param {Number} config.percentComplete a number between 0 and 1
         * @return {Object} statusColor :
         *     White (means that work is not expected to have started yet)
         *     Green (going good)
         *     Yellow (warning)
         *     Red (in trouble)
         *     Gray (work is 100% done)
         */
        calculateHealthColor:function(config) {
            var colors = Rally.util.HealthColorCalculator.colors;

            var percentComplete = config.percentComplete * 100;

            //turn dates into days since epoch, so we don't have to do date math
            //also round start date to the beginning of the day, and end date to the end of the day

            var millisecondsInDay = 86400000;

            var startDate = config.startDate;
            var endDate = config.endDate;

            if(Ext.isString(startDate)){
                startDate = new Date(Date.parse(startDate));
            }
            if(Ext.isString(endDate)){
                endDate = new Date(Date.parse(endDate));
            }

            var startDay = startDate.getTime() / millisecondsInDay;
            startDay = Math.floor(startDay);
            var endDay = endDate.getTime() / millisecondsInDay;
            endDay = Math.ceil(endDay) - 0.01;

            var asOfDay = config.asOfDate.getTime() / millisecondsInDay;

            var defaultConfig = {
                acceptanceStartDelay:  (endDay - startDay) * 0.2,
                warningDelay:  (endDay - startDay) * 0.2,
                inProgress: percentComplete > 0
            };

            config = Ext.applyIf(Ext.clone(config), defaultConfig);

            // Special cases
            if (asOfDay < startDay) {
                return colors.white;
            }

            if ((asOfDay >= startDay) &&
                (asOfDay <= (startDay + config.acceptanceStartDelay)) &&
                (! config.inProgress)) {
                return colors.green;
            }

            if (asOfDay >= endDay) {
                if (percentComplete >= 100.0) {
                    return colors.gray;
                } else {
                    return colors.red;
                }
            }

            // Red
            var redXIntercept = startDay + config.acceptanceStartDelay + config.warningDelay;
            var redSlope = 100.0 / (endDay - redXIntercept);
            var redYIntercept = -1.0 * redXIntercept * redSlope;
            var redThreshold = redSlope * asOfDay + redYIntercept;
            if (percentComplete < redThreshold) {
                return colors.red;
            }

            // Yellow
            var yellowXIntercept = startDay + config.acceptanceStartDelay;
            var yellowSlope = 100 / (endDay - yellowXIntercept);
            var yellowYIntercept = -1.0 * yellowXIntercept * yellowSlope;
            var yellowThreshold = yellowSlope * asOfDay + yellowYIntercept;
            if (percentComplete < yellowThreshold) {
                return colors.yellow;
            }

            // Green
            return colors.green;
        },

        calculateHealthColorForPortfolioItemData: function(recordData, percentDoneFieldName) {
            var today = this._getToday();
            var config = {
                percentComplete: recordData[percentDoneFieldName],
                startDate: recordData.ActualStartDate || recordData.PlannedStartDate || today,
                asOfDate: today
            };

            if(recordData[percentDoneFieldName] === 1){
                config.endDate = recordData.ActualEndDate || recordData.PlannedEndDate || today;
            } else {
                config.endDate = recordData.PlannedEndDate || today;
            }

            config.inProgress = config.percentComplete > 0;

            return this.calculateHealthColor(config);
        },

        calculateCapacityHealthColor: function(recordData, percentDoneFieldName) {
            var percent = (recordData[percentDoneFieldName] || 0) * 100.0;

            if (percent >= 100) {
                return Rally.util.HealthColorCalculator.colors.red;
            } else if (percent >= 80) {
                return Rally.util.HealthColorCalculator.colors.yellow;
            } else if (percent > 0) {
                return Rally.util.HealthColorCalculator.colors.green;
            }

            return Rally.util.HealthColorCalculator.colors.gray;
        },

        _getToday:function() {
            return new Date();
        }
    });

})();