/**
 * @class Ext.chart.series.sprite.Area
 * @extends Ext.chart.series.sprite.StackedCartesian
 *
 * Area series sprite.
 */
Ext.define('Ext.chart.series.sprite.Area', {
    alias: 'sprite.areaSeries',
    extend: 'Ext.chart.series.sprite.StackedCartesian',
 
    inheritableStatics: {
        def: {
            processors: {
                /**
                 * @cfg {Boolean} [step=false] 'true' if the area is represented with steps
                 * instead of lines.
                 */
                step: 'bool'
            },
            defaults: {
                selectionTolerance: 0,
                step: false
            }
        }
    },
 
    renderClipped: function(surface, ctx, dataClipRect) {
        var me = this,
            store = me.getStore(),
            series = me.getSeries(),
            attr = me.attr,
            dataX = attr.dataX,
            dataY = attr.dataY,
            dataStartY = attr.dataStartY,
            matrix = attr.matrix,
            x, y, i, lastX, lastY, startX, startY,
            xx = matrix.elements[0],
            dx = matrix.elements[4],
            yy = matrix.elements[3],
            dy = matrix.elements[5],
            surfaceMatrix = me.surfaceMatrix,
            markerCfg = {},
            min = Math.min(dataClipRect[0], dataClipRect[2]),
            max = Math.max(dataClipRect[0], dataClipRect[2]),
            start = Math.max(0, this.binarySearch(min)),
            end = Math.min(dataX.length - 1, this.binarySearch(max) + 1),
            renderer = attr.renderer,
            rendererData = {
                store: store
            },
            rendererChanges;
 
        ctx.beginPath();
        startX = dataX[start] * xx + dx;
        startY = dataY[start] * yy + dy;
        ctx.moveTo(startX, startY);
 
        if (attr.step) {
            lastY = startY;
 
            for (= start; i <= end; i++) {
                x = dataX[i] * xx + dx;
                y = dataY[i] * yy + dy;
                ctx.lineTo(x, lastY);
                ctx.lineTo(x, lastY = y);
            }
        }
        else {
            for (= start; i <= end; i++) {
                x = dataX[i] * xx + dx;
                y = dataY[i] * yy + dy;
                ctx.lineTo(x, y);
            }
        }
 
        if (dataStartY) {
            if (attr.step) {
                lastX = dataX[end] * xx + dx;
 
                for (= end; i >= start; i--) {
                    x = dataX[i] * xx + dx;
                    y = dataStartY[i] * yy + dy;
                    ctx.lineTo(lastX, y);
                    ctx.lineTo(lastX = x, y);
                }
            }
            else {
                for (= end; i >= start; i--) {
                    x = dataX[i] * xx + dx;
                    y = dataStartY[i] * yy + dy;
                    ctx.lineTo(x, y);
                }
            }
        }
        else {
            ctx.lineTo(dataX[end] * xx + dx, y);
            ctx.lineTo(dataX[end] * xx + dx, dy);
            ctx.lineTo(startX, dy);
            ctx.lineTo(startX, dataY[i] * yy + dy);
        }
 
        if (attr.transformFillStroke) {
            attr.matrix.toContext(ctx);
        }
 
        ctx.fill();
 
        if (attr.transformFillStroke) {
            attr.inverseMatrix.toContext(ctx);
        }
 
        ctx.beginPath();
        ctx.moveTo(startX, startY);
 
        if (attr.step) {
            for (= start; i <= end; i++) {
                x = dataX[i] * xx + dx;
                y = dataY[i] * yy + dy;
                ctx.lineTo(x, lastY);
                ctx.lineTo(x, lastY = y);
                markerCfg.translationX = surfaceMatrix.x(x, y);
                markerCfg.translationY = surfaceMatrix.y(x, y);
 
                if (renderer) {
                    // callback(fn, scope, args, delay, caller)
                    rendererChanges = Ext.callback(renderer, null,
                                                   [me, markerCfg, rendererData, i], 0, series);
                    Ext.apply(markerCfg, rendererChanges);
                }
 
                me.putMarker('markers', markerCfg, i, !renderer);
            }
        }
        else {
            for (= start; i <= end; i++) {
                x = dataX[i] * xx + dx;
                y = dataY[i] * yy + dy;
                ctx.lineTo(x, y);
                markerCfg.translationX = surfaceMatrix.x(x, y);
                markerCfg.translationY = surfaceMatrix.y(x, y);
 
                if (renderer) {
                    rendererChanges = Ext.callback(renderer, null,
                                                   [me, markerCfg, rendererData, i], 0, series);
                    Ext.apply(markerCfg, rendererChanges);
                }
 
                me.putMarker('markers', markerCfg, i, !renderer);
            }
        }
 
        if (attr.transformFillStroke) {
            attr.matrix.toContext(ctx);
        }
 
        ctx.stroke();
    }
});