/**
 * @private
 */
Ext.define('Ext.scroll.scroller.Infinite', {
    extend: 'Ext.scroll.scroller.CssPosition',

    config: {
        itemLength: 30,

        slicesCount: 6,

        sliceLengthFactor: 1,

        functions: {
            render: Ext.emptyFn,

            recycle: Ext.emptyFn,

            activate: Ext.emptyFn,

            deactivate: Ext.emptyFn,

            scope: null
        },

        direction: 'vertical'
    },

    itemsCountPerSlice: 0,

    sliceLength: 0,

    recycleIndexOffset: 0,

    constructor: function() {
        this.preparedSlices = {};

        this.emptySlices = [];

        this.slices = [];

        this.activeSlices = {
            upper: null,
            lower: null
        };

        return this.callParent(arguments);
    },

    getMaxPosition: function(determine) {
        var maxPosition = this.maxPosition;

        if (determine) {
            maxPosition.x = Infinity;
            maxPosition.y = Infinity;
        }

        return maxPosition;
    },

    getCurrentAxis: function() {
        return (this.getDirection() === 'horizontal') ? 'x' : 'y';
    },

    applyDirection: function(direction) {
        if (direction !== 'vertical' && direction !== 'horizontal') {
            direction = 'vertical';
        }

        return direction;
    },

    applyItemLength: function(length) {
        if (typeof length == 'number' && length > 0) {
            return length;
        }
        //<debug error>
        Ext.Logger.error("Invalid itemLength, must be a number greater than 0");
        //</debug>
    },

    updateItemLength: function(length, oldLength) {
        var containerSize = this.getContainerSize(true),
            sliceLengthFactor = this.getSliceLengthFactor(),
            itemsCountPerSlice,
            width, height, sliceLength;

        if (this.isAxisEnabled('x')) {
            height = containerSize.y;
            itemsCountPerSlice = Math.ceil(containerSize.x / length) * sliceLengthFactor;
            sliceLength = width = itemsCountPerSlice * length;
        }
        else {
            width = containerSize.x;
            itemsCountPerSlice = Math.ceil(containerSize.y / length) * sliceLengthFactor;
            sliceLength = height = itemsCountPerSlice * length;
        }

        this.itemsCountPerSlice = itemsCountPerSlice;
        this.sliceLength = sliceLength;

        this.setSliceSize(width, height);

        if (oldLength) {
            this.refresh();
        }
    },

    applySlicesCount: function(count) {
        if (typeof count == 'number' && count >= 4) {
            return count;
        }
        //<debug error>
        Ext.Logger.error("Invalid slicesCount, must be a number greater or equal to 4");
        //</debug>
    },

    updateSlicesCount: function(count, oldCount) {
        var slices = this.slices,
            emptySlices = this.emptySlices,
            slice, i;

        if (oldCount) {
            this.destroySlices();
        }

        for (i = 0; i < count; i++) {
            slice = this.createSlice();
            slices[i] = slice;
            emptySlices.push(slice);
        }

        this.recycleIndexOffset = Math.floor((count - 2) / 2);

        if (oldCount) {
            this.refresh();
        }
    },

    destroySlices: function() {
        var slices = this.slices,
            i, ln, slice;

        for (i = 0, ln = slices.length; i < ln; i++) {
            slice.destroy();
        }

        slices.length = 0;
        this.emptySlices.length = 0;
        this.preparedSlices.length = 0;
    },

    createSlice: function() {
        var element = this.getElement(),
            slice = element.createChild({}),
            style = slice.dom.style;

        style.position = 'absolute';
//        style.display = 'none';

        return slice;
    },

    setSliceSize: function(width, height) {
        this.getSlicesCount();

        var slices = this.slices,
            i, ln, slice, style;

        width = width + 'px';
        height = height + 'px';

        for (i = 0,ln = slices.length; i < ln; i++) {
            slice = slices[i];

            style = slice.dom.style;
            style.width = width;
            style.height = height;
        }

        return this;
    },

    prepareSlice: function(index) {
        var preparedSlices = this.preparedSlices,
            itemsCountPerSlice = this.itemsCountPerSlice,
            functions = this.getFunctions(),
            startItemIndex, endItemIndex, slice;

        if (!preparedSlices[index]) {
            slice = this.getEmptySlice();
            startItemIndex = index * itemsCountPerSlice;
            endItemIndex = startItemIndex + itemsCountPerSlice - 1;

            preparedSlices[index] = slice;

            functions.render.call(functions.scope, slice, startItemIndex, endItemIndex);
        }

        return preparedSlices[index];
    },

    getSlice: function(index) {
        if (index > 0) {
            this.prepareSlice(index - 1);
        }

        this.prepareSlice(index + 1);

        return this.prepareSlice(index);
    },

    getEmptySlice: function() {
        var recycleIndexOffset = this.recycleIndexOffset,
            upperIndex = this.upperSliceIndex - recycleIndexOffset,
            lowerIndex = this.lowerSliceIndex + recycleIndexOffset,
            preparedSlices = this.preparedSlices,
            emptySlices = this.emptySlices,
            i;

        for (i in preparedSlices) {
            if (preparedSlices.hasOwnProperty(i)) {
                if (i <= upperIndex || i >= lowerIndex) {
                    emptySlices.push(preparedSlices[i]);
                    delete preparedSlices[i];
                }
            }
        }

        return emptySlices.pop();
    },

    setSlicePosition: function(slice, position, axis) {
        var style = slice.dom.style;

        position = (-position) + 'px';

        if (axis === 'x') {
            style.left = position;
        }
        else {
            if (Ext.os.is.iOS || Ext.os.is.Android3) {
                style.webkitTransform = 'translate3d(0px, ' + position + ', 0px)';
            }
            else {
                style.top = position;
            }
        }
    },

    setActiveSlices: function(upper, lower) {
        var activeSlices = this.activeSlices,
            oldUpper = activeSlices.upper,
            oldLower = activeSlices.lower;

        if (oldUpper && oldLower) {
            if (oldUpper !== upper) {
                if (oldUpper !== lower) {
                    this.deactivateSlice(oldUpper);
                }

                if (upper !== oldLower) {
                    this.activateSlice(upper, 2);
                }
            }

            if (oldLower !== lower) {
                if (oldLower !== upper) {
                    this.deactivateSlice(oldLower);
                }

                if (lower !== oldUpper) {
                    this.activateSlice(lower, 1);
                }
            }
        }
        else {
            this.activateSlice(upper, 2);
            this.activateSlice(lower, 1);
        }

        activeSlices.upper = upper;
        activeSlices.lower = lower;

        return this;
    },

    activateSlice: function(slice, zIndex) {
        var functions = this.getFunctions(),
            style = slice.dom.style;

//        style.zIndex = zIndex;
//        style.display = '';

        functions.activate.call(functions.scope, slice);
    },

    deactivateSlice: function(slice) {
        var functions = this.getFunctions(),
            style = slice.dom.style;

//        style.display = 'none';

        if (Ext.os.is.iOS || Ext.os.is.Android3) {
            style.webkitTransform = 'translate3d(0px, -10000px, 0px)';
        }
        else {
            style.top = '-10000px';
        }

//        this.setSlicePosition(slice, 0, this.getCurrentAxis());

        functions.deactivate.call(functions.scope, slice);
    },

    doScrollTo: function(x, y) {
        var axis = this.getCurrentAxis(),
            sliceLength = this.sliceLength,
            upperPosition = ((axis === 'x') ? x : y),
            upperSliceIndex = Math.max(0, Math.floor(upperPosition / this.sliceLength)),
            lowerSliceIndex = upperSliceIndex + 1;

        this.upperSliceIndex = upperSliceIndex;
        this.lowerSliceIndex = lowerSliceIndex;

        var upperSlice = this.getSlice(upperSliceIndex),
            lowerSlice = this.getSlice(lowerSliceIndex),
            containerSize = this.getContainerSize()[axis],
            lowerPosition;

        upperPosition = upperPosition % sliceLength;
        lowerPosition = upperPosition - sliceLength;

        this.setActiveSlices(upperSlice, lowerSlice);

        this.setSlicePosition(upperSlice, upperPosition, axis);

        if (lowerPosition >= -containerSize) {
            this.setSlicePosition(lowerSlice, lowerPosition, axis);
        }
    }
});