/*
 *  Copyright 2016 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
 
/**
 * @private
 * This class is a cartesian chart which enables to draw over it.
 * Inspired by http://examples.sencha.com/extjs/6.0.1/examples/kitchensink/?charts=true#free-paint
 */
Ext.define('Ametys.plugins.admin.jvmstatus.MonitoringTool.DrawableCartesianChart', function () {

    function smoothList(points) {
        if (points.length < 3) {
            return ['M', points[0], points[1]];
        }
        var dx = [], dy = [], result = ['M'],
            i, ln = points.length;
        for (i = 0; i < ln; i += 2) {
            dx.push(points[i]);
            dy.push(points[i + 1]);
        }
        dx = Ext.draw.Draw.spline(dx);
        dy = Ext.draw.Draw.spline(dy);
        result.push(dx[0], dy[0], 'C');
        for (i = 1, ln = dx.length; i < ln; i++) {
            result.push(dx[i], dy[i]);
        }
        return result;
    }

    return {
        extend: 'Ext.chart.CartesianChart',
        xtype: 'drawable-cartesian',
        
        draw: false,

        sprite: undefined,
        lastEventX: undefined,
        lastEventY: undefined,
        list: [],

        listeners: {
            element: 'element',
            // The type of events that are supported for each framework and platform are...
            // - ExtJS on Desktop Machine: Mouse events
            // - ExtJS on Touch Device:    Mouse events + Touch events
            // - Sencha Touch:             Touch events + Drag events
            //
            // Mouse events = mousedown  / mousemove / mouseup
            // Touch events = touchstart / touchmove / touchend
            // Drag  events = dragstart  / drag      / dragend
            //
            // Since this is an ExtJS example, we can listen to Mouse events only.
            //
            // If we wanted the example to run on Sencha Touch also, we would have
            // to listen to both Mouse events and Drag events (listening to Mouse
            // events and Touch events would work as well but with the drawback
            // that ExtJS on Touch Device would send duplicate events.
            mousedown: function(e) {
                var targetElement = this,
                    me = Ext.getCmp(targetElement.id),
                    surface = me.getSurface('chart');
                if (me.draw && !me.sprite) {
                    var xy = surface.getEventXY(e),
                        x = xy[0],
                        y = xy[1];

                    me.list = [x, y, x, y];
                    me.lastEventX = x;
                    me.lastEventY = y;
                    me.sprite = surface.add({
                        type: 'path',
                        path: ['M', me.list[0], me.list[1], 'L', me.list[0] + 1e-1, me.list[1] + 1e-1],
                        lineWidth: 4,
                        lineCap: 'round',
                        lineJoin: 'round',
                        strokeStyle: new Ext.draw.Color(50, 50, 50),
                        zIndex: 1
                    });
                    surface.renderFrame();
                }
            },
            mousemove: function(e) {
                var targetElement = this,
                    me = Ext.getCmp(targetElement.id),
                    surface = me.getSurface('chart');
                if (me.draw && me.sprite) {
                    var xy = surface.getEventXY(e),
                        x = xy[0],
                        y = xy[1],
                        dx = me.lastEventX - x,
                        dy = me.lastEventY - y,
                        D = 10;

                    if (dx * dx + dy * dy < D * D) {
                        me.list.length -= 2;
                        me.list.push(x, y);
                    } else {
                        me.list.length -= 2;
                        me.list.push(me.lastEventX = x, me.lastEventY = y);
                        me.list.push(me.lastEventX + 1, me.lastEventY + 1);
                    }

                    var path = smoothList(me.list);
                    me.sprite.setAttributes({
                        path: path
                    });
                    if (Ext.os.is.Android) {
                        Ext.draw.Animator.schedule(function () {
                            surface.renderFrame();
                        }, me);
                    } else {
                        surface.renderFrame();
                    }
                }
            }
        },

        initEvents: function () {
            this.callParent(arguments);
            this.on({
                element: 'element',
                mouseup: this.onMouseUp,
                mouseleave: this.onMouseUp
            });
        },

        onMouseUp: function(e) {
            var targetElement = this,
                me = Ext.getCmp(targetElement.id);
            me.sprite = null;
        },

        onResize: function() {
            var size = this.element.getSize();
            this.getSurface('chart').setRect([0, 0, size.width, size.height]);
            this.renderFrame();
        },
        
        /**
         * Set the drawing mode active.
         * @param {Boolean} active True to set the drawing mode active, false otherwise.
         */
        setDraw: function(active)
        {
            this.draw = Ext.isBoolean(active) ? active : false;
        }
    };
});