/**
 * A Progressable mixin.
 * @private
 */
Ext.define('Ext.mixin.Progressable', {
    extend: 'Ext.Mixin',
    isProgressable: true,
 
    mixinConfig: {
        id: 'progressable'
    },
 
    config: {
 
        /**
         * @cfg {Number} minProgressInput
         * Minimum input value for this indicator
         */
        minProgressInput: 0,
 
        /**
         * @cfg {Number} maxProgressInput
         * Maximum input value for this indicator
         */
        maxProgressInput: 1,
 
        /**
         * @cfg {Number} minProgressOutput
         * Minimum output value for this indicator
         */
        minProgressOutput: 0,
 
        /**
         * @cfg {Number} maxProgressOutput
         * Maximum output value for this indicator
         */
        maxProgressOutput: 100,
 
        /**
         * @cfg {Boolean} dynamic
         *
         * When false this indicator will only receive progressStart and progressEnd commands, no 
         * progressUpdate commands will be sent.
         *
         */
        dynamic: true,
 
        /**
         * @cfg {String} state
         *
         * Current state of the progressIndicator. Should be used for switching progress states 
         * like download to upload.
         */
        state: null
    },
 
    /**
     * @private
     */
    _progressActive: false,
    _progress: 0,
    _rawProgress: 0,
 
    onStartProgress: Ext.emptyFn,
    onUpdateProgress: Ext.emptyFn,
    onEndProgress: Ext.emptyFn,
 
    startProgress: function() {
        if (!this._progressActive) {
            this._progressActive = true;
            this.onStartProgress();
            this.updateProgress(this.getMinProgressInput());
        }
    },
 
    updateProgress: function(value, state) {
        var mappedValue;
 
        if (state && state !== this.getState()) {
            this.setState(state);
        }
 
        if (value > this.getMaxProgressInput()) {
            value = this.getMaxProgressInput();
        }
 
        if (value < this.getMinProgressInput()) {
            value = this.getMinProgressInput();
        }
 
        mappedValue = this.mapValues(
            value,
            this.getMinProgressInput(),
            this.getMaxProgressInput(),
            this.getMinProgressOutput(),
            this.getMaxProgressOutput()
        );
 
        this._progress = mappedValue;
        this._rawProgress = value;
 
        if (this.getDynamic()) {
            this.onUpdateProgress(mappedValue);
        }
    },
 
    endProgress: function() {
        if (this._progressActive) {
            this._progressActive = false;
            this.updateProgress(this.getMaxProgressInput());
            this.onEndProgress();
        }
    },
 
    mapValues: function(value, inputMin, inputMax, outputMin, outputMax) {
        return (value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin;
    },
 
    setProgress: function(value) {
        this.updateProgress(value);
    },
 
    getProgress: function() {
        return this._progress;
    },
 
    getRawProgress: function() {
        return this._rawProgress;
    }
});