/*
 * Copyright (C) 2015 Apple Inc. All rights reserved.
 * Copyright (C) 2016 Devin Rousso <webkit@devinrousso.com>. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.InlineSwatch = class InlineSwatch extends WI.Object
{
    constructor(type, value, readOnly)
    {
        super();

        this._type = type;

        if (this._type === WI.InlineSwatch.Type.Bezier || this._type === WI.InlineSwatch.Type.Spring)
            this._swatchElement = WI.ImageUtilities.useSVGSymbol("Images/CubicBezier.svg");
        else if (this._type === WI.InlineSwatch.Type.Variable)
            this._swatchElement = WI.ImageUtilities.useSVGSymbol("Images/CSSVariable.svg");
        else
            this._swatchElement = document.createElement("span");

        this._swatchElement.classList.add("inline-swatch", this._type.split("-").lastValue);

        if (readOnly)
            this._swatchElement.classList.add("read-only");
        else {
            switch (this._type) {
            case WI.InlineSwatch.Type.Color:
                this._swatchElement.title = WI.UIString("Click to select a color\nShift-click to switch color formats");
                break;
            case WI.InlineSwatch.Type.Gradient:
                this._swatchElement.title = WI.UIString("Edit custom gradient");
                break;
            case WI.InlineSwatch.Type.Bezier:
                this._swatchElement.title = WI.UIString("Edit \u201Ccubic-bezier\u201D function");
                break;
            case WI.InlineSwatch.Type.Spring:
                this._swatchElement.title = WI.UIString("Edit \u201Cspring\u201D function");
                break;
            case WI.InlineSwatch.Type.Variable:
                this._swatchElement.title = WI.UIString("Click to view variable value\nShift-click to replace variable with value");
                break;
            case WI.InlineSwatch.Type.Image:
                this._swatchElement.title = WI.UIString("View Image");
                break;
            default:
                WI.reportInternalError(`Unknown InlineSwatch type "${type}"`);
                break;
            }

            this._swatchElement.addEventListener("click", this._swatchElementClicked.bind(this));
            if (this._type === WI.InlineSwatch.Type.Color)
                this._swatchElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this));
        }

        this._swatchInnerElement = this._swatchElement.createChild("span");

        this._value = value || this._fallbackValue();
        this._valueEditor = null;

        this._updateSwatch();
    }

    // Public

    get element()
    {
        return this._swatchElement;
    }

    get value()
    {
        if (typeof this._value === "function")
            return this._value();
        return this._value;
    }

    set value(value)
    {
        this._value = value;
        this._updateSwatch(true);
    }

    // Popover delegate

    didDismissPopover(popover)
    {
        if (!this._valueEditor)
            return;

        if (this._valueEditor.removeListeners)
            this._valueEditor.removeListeners();

        if (this._valueEditor instanceof WI.Object)
            this._valueEditor.removeEventListener(null, null, this);

        this._valueEditor = null;

        this.dispatchEventToListeners(WI.InlineSwatch.Event.Deactivated);
    }

    // Private

    _fallbackValue()
    {
        switch (this._type) {
        case WI.InlineSwatch.Type.Bezier:
            return WI.CubicBezier.fromString("linear");
        case WI.InlineSwatch.Type.Gradient:
            return WI.Gradient.fromString("linear-gradient(transparent, transparent)");
        case WI.InlineSwatch.Type.Spring:
            return WI.Spring.fromString("1 100 10 0");
        case WI.InlineSwatch.Type.Color:
            return WI.Color.fromString("white");
        default:
            return null;
        }
    }

    _updateSwatch(dontFireEvents)
    {
        let value = this.value;

        if (this._type === WI.InlineSwatch.Type.Color || this._type === WI.InlineSwatch.Type.Gradient)
            this._swatchInnerElement.style.background = value ? value.toString() : null;
        else if (this._type === WI.InlineSwatch.Type.Image)
            this._swatchInnerElement.style.setProperty("background-image", `url(${value.src})`);

        if (!dontFireEvents)
            this.dispatchEventToListeners(WI.InlineSwatch.Event.ValueChanged, {value});
    }

    _swatchElementClicked(event)
    {
        event.stop();

        let value = this.value;

        if (event.shiftKey && value) {
            if (this._type === WI.InlineSwatch.Type.Color) {
                let nextFormat = value.nextFormat();
                console.assert(nextFormat);
                if (nextFormat) {
                    value.format = nextFormat;
                    this._updateSwatch();
                }
                return;
            }

            if (this._type === WI.InlineSwatch.Type.Variable) {
                // Force the swatch to replace the displayed text with the variable's value.
                this._swatchElement.remove();
                this._updateSwatch();
                return;
            }
        }

        if (this._valueEditor)
            return;

        if (!value)
            value = this._fallbackValue();

        let bounds = WI.Rect.rectFromClientRect(this._swatchElement.getBoundingClientRect());
        let popover = new WI.Popover(this);

        popover.windowResizeHandler = () => {
            let bounds = WI.Rect.rectFromClientRect(this._swatchElement.getBoundingClientRect());
            popover.present(bounds.pad(2), [WI.RectEdge.MIN_X]);
        };

        this._valueEditor = null;
        switch (this._type) {
        case WI.InlineSwatch.Type.Color:
            this._valueEditor = new WI.ColorPicker;
            this._valueEditor.addEventListener(WI.ColorPicker.Event.ColorChanged, this._valueEditorValueDidChange, this);
            this._valueEditor.addEventListener(WI.ColorPicker.Event.FormatChanged, (event) => popover.update());
            break;

        case WI.InlineSwatch.Type.Gradient:
            this._valueEditor = new WI.GradientEditor;
            this._valueEditor.addEventListener(WI.GradientEditor.Event.GradientChanged, this._valueEditorValueDidChange, this);
            this._valueEditor.addEventListener(WI.GradientEditor.Event.ColorPickerToggled, (event) => popover.update());
            break;

        case WI.InlineSwatch.Type.Bezier:
            this._valueEditor = new WI.BezierEditor;
            this._valueEditor.addEventListener(WI.BezierEditor.Event.BezierChanged, this._valueEditorValueDidChange, this);
            break;

        case WI.InlineSwatch.Type.Spring:
            this._valueEditor = new WI.SpringEditor;
            this._valueEditor.addEventListener(WI.SpringEditor.Event.SpringChanged, this._valueEditorValueDidChange, this);
            break;

        case WI.InlineSwatch.Type.Variable:
            this._valueEditor = {};

            this._valueEditor.element = document.createElement("div");
            this._valueEditor.element.classList.add("inline-swatch-variable-popover");

            this._valueEditor.codeMirror = WI.CodeMirrorEditor.create(this._valueEditor.element, {
                mode: "css",
                readOnly: true,
            });
            this._valueEditor.codeMirror.on("update", () => {
                popover.update();
            });
            break;

        case WI.InlineSwatch.Type.Image:
            if (value.src) {
                this._valueEditor = {};
                this._valueEditor.element = document.createElement("img");
                this._valueEditor.element.src = value.src;
                this._valueEditor.element.classList.add("show-grid");
                this._valueEditor.element.style.setProperty("max-width", "50vw");
                this._valueEditor.element.style.setProperty("max-height", "50vh");
            }
            break;
        }

        if (!this._valueEditor)
            return;

        popover.content = this._valueEditor.element;
        popover.present(bounds.pad(2), [WI.RectEdge.MIN_X]);

        this.dispatchEventToListeners(WI.InlineSwatch.Event.Activated);

        switch (this._type) {
        case WI.InlineSwatch.Type.Color:
            this._valueEditor.color = value;
            break;

        case WI.InlineSwatch.Type.Gradient:
            this._valueEditor.gradient = value;
            break;

        case WI.InlineSwatch.Type.Bezier:
            this._valueEditor.bezier = value;
            break;

        case WI.InlineSwatch.Type.Spring:
            this._valueEditor.spring = value;
            break;

        case WI.InlineSwatch.Type.Variable: {
            let codeMirror = this._valueEditor.codeMirror;
            codeMirror.setValue(value);

            const range = null;
            function optionsForType(type) {
                return {
                    allowedTokens: /\btag\b/,
                    callback(marker, valueObject, valueString) {
                        let swatch = new WI.InlineSwatch(type, valueObject, true);
                        codeMirror.setUniqueBookmark({line: 0, ch: 0}, swatch.element);
                    }
                };
            }
            createCodeMirrorColorTextMarkers(codeMirror, range, optionsForType(WI.InlineSwatch.Type.Color));
            createCodeMirrorGradientTextMarkers(codeMirror, range, optionsForType(WI.InlineSwatch.Type.Gradient));
            createCodeMirrorCubicBezierTextMarkers(codeMirror, range, optionsForType(WI.InlineSwatch.Type.Bezier));
            createCodeMirrorSpringTextMarkers(codeMirror, range, optionsForType(WI.InlineSwatch.Type.Spring));
            break;
        }
        }
    }

    _valueEditorValueDidChange(event)
    {
        if (this._type === WI.InlineSwatch.Type.Color)
            this._value = event.data.color;
        else if (this._type === WI.InlineSwatch.Type.Gradient)
            this._value = event.data.gradient;
        else if (this._type === WI.InlineSwatch.Type.Bezier)
            this._value = event.data.bezier;
        else if (this._type === WI.InlineSwatch.Type.Spring)
            this._value = event.data.spring;

        this._updateSwatch();
    }

    _handleContextMenuEvent(event)
    {
        let value = this.value;
        if (!value)
            return;

        let contextMenu = WI.ContextMenu.createFromEvent(event);

        if (value.isKeyword() && value.format !== WI.Color.Format.Keyword) {
            contextMenu.appendItem(WI.UIString("Format: Keyword"), () => {
                value.format = WI.Color.Format.Keyword;
                this._updateSwatch();
            });
        }

        let hexInfo = this._getNextValidHEXFormat();
        if (hexInfo) {
            contextMenu.appendItem(hexInfo.title, () => {
                value.format = hexInfo.format;
                this._updateSwatch();
            });
        }

        if (value.simple && value.format !== WI.Color.Format.HSL) {
            contextMenu.appendItem(WI.UIString("Format: HSL"), () => {
                value.format = WI.Color.Format.HSL;
                this._updateSwatch();
            });
        } else if (value.format !== WI.Color.Format.HSLA) {
            contextMenu.appendItem(WI.UIString("Format: HSLA"), () => {
                value.format = WI.Color.Format.HSLA;
                this._updateSwatch();
            });
        }

        if (value.simple && value.format !== WI.Color.Format.RGB) {
            contextMenu.appendItem(WI.UIString("Format: RGB"), () => {
                value.format = WI.Color.Format.RGB;
                this._updateSwatch();
            });
        } else if (value.format !== WI.Color.Format.RGBA) {
            contextMenu.appendItem(WI.UIString("Format: RGBA"), () => {
                value.format = WI.Color.Format.RGBA;
                this._updateSwatch();
            });
        }
    }

    _getNextValidHEXFormat()
    {
        if (this._type !== WI.InlineSwatch.Type.Color)
            return false;

        let value = this.value;

        function hexMatchesCurrentColor(hexInfo) {
            let nextIsSimple = hexInfo.format === WI.Color.Format.ShortHEX || hexInfo.format === WI.Color.Format.HEX;
            if (nextIsSimple && !value.simple)
                return false;

            let nextIsShort = hexInfo.format === WI.Color.Format.ShortHEX || hexInfo.format === WI.Color.Format.ShortHEXAlpha;
            if (nextIsShort && !value.canBeSerializedAsShortHEX())
                return false;

            return true;
        }

        const hexFormats = [
            {
                format: WI.Color.Format.ShortHEX,
                title: WI.UIString("Format: Short Hex")
            },
            {
                format: WI.Color.Format.ShortHEXAlpha,
                title: WI.UIString("Format: Short Hex with Alpha")
            },
            {
                format: WI.Color.Format.HEX,
                title: WI.UIString("Format: Hex")
            },
            {
                format: WI.Color.Format.HEXAlpha,
                title: WI.UIString("Format: Hex with Alpha")
            }
        ];

        let currentColorIsHEX = hexFormats.some((info) => info.format === value.format);

        for (let i = 0; i < hexFormats.length; ++i) {
            if (currentColorIsHEX && value.format !== hexFormats[i].format)
                continue;

            for (let j = ~~currentColorIsHEX; j < hexFormats.length; ++j) {
                let nextIndex = (i + j) % hexFormats.length;
                if (hexMatchesCurrentColor(hexFormats[nextIndex]))
                    return hexFormats[nextIndex];
            }
            return null;
        }
        return hexFormats[0];
    }
};

WI.InlineSwatch.Type = {
    Color: "inline-swatch-type-color",
    Gradient: "inline-swatch-type-gradient",
    Bezier: "inline-swatch-type-bezier",
    Spring: "inline-swatch-type-spring",
    Variable: "inline-swatch-type-variable",
    Image: "inline-swatch-type-image",
};

WI.InlineSwatch.Event = {
    ValueChanged: "inline-swatch-value-changed",
    Activated: "inline-swatch-activated",
    Deactivated: "inline-swatch-deactivated",
};
