'use strict';
import H from '../../parts/Globals.js';
import '../../parts/Utilities.js';

var Annotation = H.Annotation,
    CrookedLine = Annotation.types.crookedLine,
    ControlPoint = Annotation.ControlPoint,
    MockPoint = Annotation.MockPoint;

function getSecondCoordinate(p1, p2, x) {
    return (p2.y - p1.y) / (p2.x - p1.x) * (x - p1.x) + p1.y;
}

/**
 * @class
 * @extends Annotation.CrookedLine
 * @memberOf Annotation
 **/
function Tunnel() {
    CrookedLine.apply(this, arguments);
}

H.extendAnnotation(
    Tunnel,
    CrookedLine,
    /** @lends Annotation.Tunnel# */
    {
        getPointsOptions: function () {
            var pointsOptions =
                CrookedLine.prototype.getPointsOptions.call(this);

            pointsOptions[2] = this.heightPointOptions(pointsOptions[1]);
            pointsOptions[3] = this.heightPointOptions(pointsOptions[0]);

            return pointsOptions;
        },

        getControlPointsOptions: function () {
            return this.getPointsOptions().slice(0, 2);
        },

        heightPointOptions: function (pointOptions) {
            var heightPointOptions = H.merge(pointOptions);

            heightPointOptions.y += this.options.typeOptions.height;

            return heightPointOptions;
        },

        addControlPoints: function () {
            CrookedLine.prototype.addControlPoints.call(this);

            var options = this.options,
                controlPoint = new ControlPoint(
                    this.chart,
                    this,
                    H.merge(
                        options.controlPointOptions,
                        options.typeOptions.heightControlPoint
                    ),
                    2
                );

            this.controlPoints.push(controlPoint);

            options.typeOptions.heightControlPoint = controlPoint.options;
        },

        addShapes: function () {
            this.addLine();
            this.addBackground();
        },

        addLine: function () {
            var line = this.initShape(
                H.merge(this.options.typeOptions.line, {
                    type: 'path',
                    points: [
                        this.points[0],
                        this.points[1],
                        function (target) {
                            var pointOptions = MockPoint.pointToOptions(
                                target.annotation.points[2]
                            );

                            pointOptions.command = 'M';

                            return pointOptions;
                        },
                        this.points[3]
                    ]
                }),
                false
            );

            this.options.typeOptions.line = line.options;
        },

        addBackground: function () {
            var background = this.initShape(H.merge(
                this.options.typeOptions.background,
                {
                    type: 'path',
                    points: this.points.slice()
                }
            ));

            this.options.typeOptions.background = background.options;
        },

        /**
         * Translate start or end ("left" or "right") side of the tunnel.
         *
         * @param {number} dx - the amount of x translation
         * @param {number} dy - the amount of y translation
         * @param {boolean} [end] - whether to translate start or end side
         */
        translateSide: function (dx, dy, end) {
            var topIndex = Number(end),
                bottomIndex = topIndex === 0 ? 3 : 2;

            this.translatePoint(dx, dy, topIndex);
            this.translatePoint(dx, dy, bottomIndex);
        },

        /**
         * Translate height of the tunnel.
         *
         * @param {number} dh - the amount of height translation
         */
        translateHeight: function (dh) {
            this.translatePoint(0, dh, 2);
            this.translatePoint(0, dh, 3);

            this.options.typeOptions.height =
                this.points[3].y - this.points[0].y;
        }
    },

    /**
     * A tunnel annotation.
     *
     * @extends annotations.crookedLine
     * @sample highcharts/annotations-advanced/tunnel/
     *         Tunnel
     * @product highstock
     * @optionparent annotations.tunnel
     */
    {
        typeOptions: {
            xAxis: 0,
            yAxis: 0,
            /**
             * Background options.
             *
             * @type {Object}
             * @excluding height, point, points, r, type, width, markerEnd,
             *            markerStart
             */
            background: {
                fill: 'rgba(130, 170, 255, 0.4)',
                strokeWidth: 0
            },
            line: {
                strokeWidth: 1
            },
            /**
             * The height of the annotation in terms of yAxis.
             */
            height: -2,


            /**
             * Options for the control point which controls
             * the annotation's height.
             *
             * @extends annotations.crookedLine.controlPointOptions
             * @excluding positioner, events
             */
            heightControlPoint: {
                positioner: function (target) {
                    var startXY = MockPoint.pointToPixels(target.points[2]),
                        endXY = MockPoint.pointToPixels(target.points[3]),
                        x = (startXY.x + endXY.x) / 2;

                    return {
                        x: x - this.graphic.width / 2,
                        y: getSecondCoordinate(startXY, endXY, x) -
                        this.graphic.height / 2
                    };
                },
                events: {
                    drag: function (e, target) {
                        if (
                            target.chart.isInsidePlot(
                                e.chartX - target.chart.plotLeft,
                                e.chartY - target.chart.plotTop
                            )
                        ) {
                            target.translateHeight(
                                this.mouseMoveToTranslation(e).y
                            );

                            target.redraw(false);
                        }
                    }
                }
            }
        },

        /**
         * @extends annotations.crookedLine.controlPointOptions
         * @excluding positioner, events
         */
        controlPointOptions: {
            events: {
                drag: function (e, target) {
                    if (
                        target.chart.isInsidePlot(
                            e.chartX - target.chart.plotLeft,
                            e.chartY - target.chart.plotTop
                        )
                    ) {
                        var translation = this.mouseMoveToTranslation(e);

                        target.translateSide(
                            translation.x,
                            translation.y,
                            this.index
                        );

                        target.redraw(false);
                    }
                }
            }
        }
    }
);

Annotation.types.tunnel = Tunnel;

export default Tunnel;
