/*
 * Copyright (C) 2014-2015 Apple Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

WI.GradientSlider = class GradientSlider extends WI.Object
{
    constructor(delegate)
    {
        super();

        this.delegate = delegate;

        this._element = null;
        this._stops = [];
        this._knobs = [];

        this._selectedKnob = null;
        this._canvas = document.createElement("canvas");

        this._keyboardShortcutEsc = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Escape);
    }

    // Public

    get element()
    {
        if (!this._element) {
            this._element = document.createElement("div");
            this._element.className = "gradient-slider";
            this._element.appendChild(this._canvas);

            this._addArea = this._element.appendChild(document.createElement("div"));
            this._addArea.addEventListener("mouseover", this);
            this._addArea.addEventListener("mousemove", this);
            this._addArea.addEventListener("mouseout", this);
            this._addArea.addEventListener("click", this);
            this._addArea.className = WI.GradientSlider.AddAreaClassName;
        }
        return this._element;
    }

    get stops()
    {
        return this._stops;
    }

    set stops(stops)
    {
        this._stops = stops;

        this._updateStops();
    }

    get selectedStop()
    {
        return this._selectedKnob ? this._selectedKnob.stop : null;
    }

    // Protected

    handleEvent(event)
    {
        switch (event.type) {
        case "mouseover":
            this._handleMouseover(event);
            break;
        case "mousemove":
            this._handleMousemove(event);
            break;
        case "mouseout":
            this._handleMouseout(event);
            break;
        case "click":
            this._handleClick(event);
            break;
        }
    }

    handleKeydownEvent(event)
    {
        if (!this._keyboardShortcutEsc.matchesEvent(event) || !this._selectedKnob || !this._selectedKnob.selected)
            return false;

        this._selectedKnob.selected = false;

        return true;
    }

    knobXDidChange(knob)
    {
        knob.stop.offset = knob.x / WI.GradientSlider.Width;
        this._sortStops();
        this._updateCanvas();
    }

    knobCanDetach(knob)
    {
        return this._knobs.length > 2;
    }

    knobWillDetach(knob)
    {
        knob.element.classList.add(WI.GradientSlider.DetachingClassName);

        this._stops.remove(knob.stop);
        this._knobs.remove(knob);
        this._sortStops();
        this._updateCanvas();
    }

    knobSelectionChanged(knob)
    {
        if (this._selectedKnob && this._selectedKnob !== knob && knob.selected)
            this._selectedKnob.selected = false;

        this._selectedKnob = knob.selected ? knob : null;

        if (this.delegate && typeof this.delegate.gradientSliderStopWasSelected === "function")
            this.delegate.gradientSliderStopWasSelected(this, knob.stop);

        if (this._selectedKnob)
            WI.addWindowKeydownListener(this);
        else
            WI.removeWindowKeydownListener(this);
    }

    // Private

    _handleMouseover(event)
    {
        this._updateShadowKnob(event);
    }

    _handleMousemove(event)
    {
        this._updateShadowKnob(event);
    }

    _handleMouseout(event)
    {
        if (!this._shadowKnob)
            return;

        this._shadowKnob.element.remove();
        delete this._shadowKnob;
    }

    _handleClick(event)
    {
        this._updateShadowKnob(event);

        this._knobs.push(this._shadowKnob);

        this._shadowKnob.element.classList.remove(WI.GradientSlider.ShadowClassName);

        var stop = {offset: this._shadowKnob.x / WI.GradientSlider.Width, color: this._shadowKnob.wellColor};
        this._stops.push(stop);
        this._sortStops();
        this._updateStops();

        this._knobs[this._stops.indexOf(stop)].selected = true;

        delete this._shadowKnob;
    }

    _updateShadowKnob(event)
    {
        if (!this._shadowKnob) {
            this._shadowKnob = new WI.GradientSliderKnob(this);
            this._shadowKnob.element.classList.add(WI.GradientSlider.ShadowClassName);
            this.element.appendChild(this._shadowKnob.element);
        }

        this._shadowKnob.x = window.webkitConvertPointFromPageToNode(this.element, new WebKitPoint(event.pageX, event.pageY)).x;

        var colorData = this._canvas.getContext("2d").getImageData(this._shadowKnob.x - 1, 0, 1, 1).data;
        this._shadowKnob.wellColor = new WI.Color(WI.Color.Format.RGB, [colorData[0], colorData[1], colorData[2], colorData[3] / 255]);
    }

    _sortStops()
    {
        this._stops.sort(function(a, b) {
            return a.offset - b.offset;
        });
    }

    _updateStops()
    {
        this._updateCanvas();
        this._updateKnobs();
    }

    _updateCanvas()
    {
        var w = WI.GradientSlider.Width;
        var h = WI.GradientSlider.Height;

        this._canvas.width = w;
        this._canvas.height = h;

        var ctx = this._canvas.getContext("2d");
        var gradient = ctx.createLinearGradient(0, 0, w, 0);
        for (var stop of this._stops)
            gradient.addColorStop(stop.offset, stop.color);

        ctx.clearRect(0, 0, w, h);
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, w, h);

        if (this.delegate && typeof this.delegate.gradientSliderStopsDidChange === "function")
            this.delegate.gradientSliderStopsDidChange(this);
    }

    _updateKnobs()
    {
        var selectedStop = this._selectedKnob ? this._selectedKnob.stop : null;

        while (this._knobs.length > this._stops.length)
            this._knobs.pop().element.remove();

        while (this._knobs.length < this._stops.length) {
            var knob = new WI.GradientSliderKnob(this);
            this.element.appendChild(knob.element);
            this._knobs.push(knob);
        }

        for (var i = 0; i < this._stops.length; ++i) {
            var stop = this._stops[i];
            var knob = this._knobs[i];

            knob.stop = stop;
            knob.x = Math.round(stop.offset * WI.GradientSlider.Width);
            knob.selected = stop === selectedStop;
        }
    }
};

WI.GradientSlider.Width = 238;
WI.GradientSlider.Height = 19;

WI.GradientSlider.AddAreaClassName = "add-area";
WI.GradientSlider.DetachingClassName = "detaching";
WI.GradientSlider.ShadowClassName = "shadow";

WI.GradientSliderKnob = class GradientSliderKnob extends WI.Object
{
    constructor(delegate)
    {
        super();

        this._x = 0;
        this._y = 0;
        this._stop = null;

        this.delegate = delegate;

        this._element = document.createElement("div");
        this._element.className = "gradient-slider-knob";

        // Checkers pattern.
        this._element.appendChild(document.createElement("img"));

        this._well = this._element.appendChild(document.createElement("div"));

        this._element.addEventListener("mousedown", this);
    }

    // Public

    get element()
    {
        return this._element;
    }

    get stop()
    {
        return this._stop;
    }

    set stop(stop)
    {
        this.wellColor = stop.color;
        this._stop = stop;
    }

    get x()
    {
        return this._x;
    }

    set x(x) {
        this._x = x;
        this._updateTransform();
    }

    get y()
    {
        return this._x;
    }

    set y(y) {
        this._y = y;
        this._updateTransform();
    }

    get wellColor()
    {
        return this._wellColor;
    }

    set wellColor(color)
    {
        this._wellColor = color;
        this._well.style.backgroundColor = color;
    }

    get selected()
    {
        return this._element.classList.contains(WI.GradientSliderKnob.SelectedClassName);
    }

    set selected(selected)
    {
        if (this.selected === selected)
            return;

        this._element.classList.toggle(WI.GradientSliderKnob.SelectedClassName, selected);

        if (this.delegate && typeof this.delegate.knobSelectionChanged === "function")
            this.delegate.knobSelectionChanged(this);
    }

    // Protected

    handleEvent(event)
    {
        event.preventDefault();
        event.stopPropagation();

        switch (event.type) {
        case "mousedown":
            this._handleMousedown(event);
            break;
        case "mousemove":
            this._handleMousemove(event);
            break;
        case "mouseup":
            this._handleMouseup(event);
            break;
        case "transitionend":
            this._handleTransitionEnd(event);
            break;
        }
    }

    // Private

    _handleMousedown(event)
    {
        this._moved = false;
        this._detaching = false;

        window.addEventListener("mousemove", this, true);
        window.addEventListener("mouseup", this, true);

        this._startX = this.x;
        this._startMouseX = event.pageX;
        this._startMouseY = event.pageY;
    }

    _handleMousemove(event)
    {
        var w = WI.GradientSlider.Width;

        this._moved = true;

        if (!this._detaching && Math.abs(event.pageY - this._startMouseY) > 50) {
            this._detaching = this.delegate && typeof this.delegate.knobCanDetach === "function" && this.delegate.knobCanDetach(this);
            if (this._detaching && this.delegate && typeof this.delegate.knobWillDetach === "function") {
                var translationFromParentToBody = window.webkitConvertPointFromNodeToPage(this.element.parentNode, new WebKitPoint(0, 0));
                this._startMouseX -= translationFromParentToBody.x;
                this._startMouseY -= translationFromParentToBody.y;
                document.body.appendChild(this.element);
                this.delegate.knobWillDetach(this);
            }
        }

        var x = this._startX + event.pageX - this._startMouseX;
        if (!this._detaching)
            x = Math.min(Math.max(0, x), w);
        this.x = x;

        if (this._detaching)
            this.y = event.pageY - this._startMouseY;
        else if (this.delegate && typeof this.delegate.knobXDidChange === "function")
            this.delegate.knobXDidChange(this);
    }

    _handleMouseup(event)
    {
        window.removeEventListener("mousemove", this, true);
        window.removeEventListener("mouseup", this, true);

        if (this._detaching) {
            this.element.addEventListener("transitionend", this);
            this.element.classList.add(WI.GradientSliderKnob.FadeOutClassName);
            this.selected = false;
        } else if (!this._moved)
            this.selected = !this.selected;
    }

    _handleTransitionEnd(event)
    {
        this.element.removeEventListener("transitionend", this);
        this.element.classList.remove(WI.GradientSliderKnob.FadeOutClassName);
        this.element.remove();
    }

    _updateTransform()
    {
        this.element.style.webkitTransform = "translate3d(" + this._x + "px, " + this._y + "px, 0)";
    }
};

WI.GradientSliderKnob.SelectedClassName = "selected";
WI.GradientSliderKnob.FadeOutClassName = "fade-out";
