/*
 * Copyright (C) 2014, 2021 Apple Inc. All rights reserved.
 * Copyright (C) 2015 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.GradientEditor = class GradientEditor extends WI.Object
{
    constructor()
    {
        super();

        this._element = document.createElement("div");
        this._element.classList.add("gradient-editor");

        this._gradient = null;
        this._gradientTypes = {
            "linear-gradient": {
                type: WI.LinearGradient,
                label: WI.UIString("Linear Gradient"),
                repeats: false
            },
            "radial-gradient": {
                type: WI.RadialGradient,
                label: WI.UIString("Radial Gradient"),
                repeats: false
            },
            "conic-gradient": {
                type: WI.ConicGradient,
                label: WI.UIString("Conic Gradient"),
                repeats: false
            },
            "repeating-linear-gradient": {
                type: WI.LinearGradient,
                label: WI.UIString("Repeating Linear Gradient"),
                repeats: true
            },
            "repeating-radial-gradient": {
                type: WI.RadialGradient,
                label: WI.UIString("Repeating Radial Gradient"),
                repeats: true
            },
            "repeating-conic-gradient": {
                type: WI.ConicGradient,
                label: WI.UIString("Repeating Conic Gradient"),
                repeats: true
            },
        };
        this._editingColor = false;

        this._gradientTypePicker = this._element.appendChild(document.createElement("select"));
        this._gradientTypePicker.classList.add("gradient-type-select");
        for (let type in this._gradientTypes) {
            let option = this._gradientTypePicker.appendChild(document.createElement("option"));
            option.value = type;
            option.text = this._gradientTypes[type].label;
        }
        this._gradientTypePicker.addEventListener("change", this._gradientTypeChanged.bind(this));

        this._gradientSlider = new WI.GradientSlider(this);
        this._element.appendChild(this._gradientSlider.element);

        this._colorPicker = new WI.ColorPicker;
        this._colorPicker.colorSquare.dimension = 195;
        this._colorPicker.enableColorComponentInputs = false;
        this._colorPicker.addEventListener(WI.ColorPicker.Event.ColorChanged, this._colorPickerColorChanged, this);

        let angleContainerElement = this._element.appendChild(document.createElement("div"));
        angleContainerElement.classList.add("gradient-angle");
        angleContainerElement.append(WI.UIString("Angle"));

        let boundAngleValueChanged = this._angleValueChanged.bind(this);

        this._angleSliderElement = angleContainerElement.appendChild(document.createElement("input"));
        this._angleSliderElement.type = "range";
        this._angleSliderElement.addEventListener("input", boundAngleValueChanged);

        this._angleInputElement = angleContainerElement.appendChild(document.createElement("input"));
        this._angleInputElement.type = "number";
        this._angleInputElement.addEventListener("input", boundAngleValueChanged);

        this._angleUnitsSelectElement = angleContainerElement.appendChild(document.createElement("select"));
        this._angleUnitsSelectElement.addEventListener("change", this._angleUnitsChanged.bind(this));

        const angleUnitsData = [
            {name: WI.Gradient.AngleUnits.DEG, min: 0, max: 360, step: 1},
            {name: WI.Gradient.AngleUnits.RAD, min: 0, max: 2 * Math.PI, step: 0.01},
            {name: WI.Gradient.AngleUnits.GRAD, min: 0, max: 400, step: 1},
            {name: WI.Gradient.AngleUnits.TURN, min: 0, max: 1, step: 0.01}
        ];

        this._angleUnitsConfiguration = new Map(angleUnitsData.map(({name, min, max, step}) => {
            let optionElement = this._angleUnitsSelectElement.appendChild(document.createElement("option"));
            optionElement.value = optionElement.textContent = name;

            return [name, {element: optionElement, min, max, step}];
        }));
    }

    get element()
    {
        return this._element;
    }

    set gradient(gradient)
    {
        if (!gradient)
            return;

        const isLinear = gradient instanceof WI.LinearGradient;
        const isRadial = gradient instanceof WI.RadialGradient;
        const isConic = gradient instanceof WI.ConicGradient;
        console.assert(isLinear || isRadial || isConic);
        if (!isLinear && !isRadial && !isConic)
            return;

        this._gradient = gradient;
        this._gradientSlider.stops = this._gradient.stops;
        if (isLinear) {
            this._gradientTypePicker.value = this._gradient.repeats ? "repeating-linear-gradient" : "linear-gradient";
            this._angleUnitsChanged();
        } else if (isRadial)
            this._gradientTypePicker.value = this._gradient.repeats ? "repeating-radial-gradient" : "radial-gradient";
        else {
            this._gradientTypePicker.value = this._gradient.repeats ? "repeating-conic-gradient" : "conic-gradient";
            this._angleUnitsChanged();
        }

        this._updateCSSClassForGradientType();
    }

    get gradient()
    {
        return this._gradient;
    }

    // Protected

    gradientSliderStopsDidChange(gradientSlider)
    {
        this._gradient.stops = gradientSlider.stops;

        this.dispatchEventToListeners(WI.GradientEditor.Event.GradientChanged, {gradient: this._gradient});
    }

    gradientSliderStopWasSelected(gradientSlider, stop)
    {
        const selectedStop = gradientSlider.selectedStop;
        if (selectedStop && !this._editingColor) {
            this._element.appendChild(this._colorPicker.element);
            this._element.classList.add("editing-color");
            this._colorPicker.color = selectedStop.color;
            this._editingColor = true;
        } else if (!selectedStop) {
            this._colorPicker.element.remove();
            this._element.classList.remove("editing-color");
            this._editingColor = false;
        }

        // Ensure the angle input is not focused since, if it were, it'd make a scrollbar appear as we
        // animate the popover's frame to fit its new content.
        this._angleInputElement.blur();

        this.dispatchEventToListeners(WI.GradientEditor.Event.ColorPickerToggled);
        this.dispatchEventToListeners(WI.GradientEditor.Event.GradientChanged, {gradient: this._gradient});
    }

    // Private

    _updateCSSClassForGradientType()
    {
        const isRadial = this._gradient instanceof WI.RadialGradient;
        this._element.classList.toggle("radial-gradient", isRadial);

        this.dispatchEventToListeners(WI.GradientEditor.Event.ColorPickerToggled);
    }

    _gradientTypeChanged(event)
    {
        const descriptor = this._gradientTypes[this._gradientTypePicker.value];
        if (!(this._gradient instanceof descriptor.type)) {
            switch (descriptor.type) {
            case WI.LinearGradient:
                this._gradient = new WI.LinearGradient({value: 180, units: WI.Gradient.AngleUnits.DEG}, this._gradient.stops);
                this._angleUnitsChanged();
                break;
            case WI.RadialGradient:
                this._gradient = new WI.RadialGradient("", this._gradient.stops);
                break;
            case WI.ConicGradient:
                this._gradient = new WI.ConicGradient({value: 0, units: WI.Gradient.AngleUnits.DEG}, null, this._gradient.stops);
                this._angleUnitsChanged();
                break;
            }

            this._updateCSSClassForGradientType();
        }
        this._gradient.repeats = descriptor.repeats;

        this.dispatchEventToListeners(WI.GradientEditor.Event.GradientChanged, {gradient: this._gradient});
    }

    _colorPickerColorChanged(event)
    {
        this._gradientSlider.selectedStop.color = event.target.color;
        this._gradientSlider.stops = this._gradient.stops;

        this.dispatchEventToListeners(WI.GradientEditor.Event.GradientChanged, {gradient: this._gradient});
    }

    _angleValueChanged(event)
    {
        switch (event.target) {
        case this._angleInputElement:
            this._gradient.angleValue = this._angleSliderElement.value = parseFloat(this._angleInputElement.value) || 0;
            break;
        case this._angleSliderElement:
            this._gradient.angleValue = this._angleInputElement.value = parseFloat(this._angleSliderElement.value) || 0;
            break;
        default:
            WI.reportInternalError("Input event fired for disabled color component input");
            return;
        }

        this.dispatchEventToListeners(WI.GradientEditor.Event.GradientChanged, {gradient: this._gradient});
    }

    _angleUnitsChanged(event)
    {
        let units = this._angleUnitsSelectElement.value;
        let configuration = this._angleUnitsConfiguration.get(units);
        if (!configuration) {
            WI.reportInternalError(`Missing configuration data for selected angle units "${units}"`);
            return;
        }

        this._gradient.angleUnits = units;

        this._angleInputElement.min = this._angleSliderElement.min = configuration.min;
        this._angleInputElement.max = this._angleSliderElement.max = configuration.max;
        this._angleInputElement.step = this._angleSliderElement.step = configuration.step;
        this._angleInputElement.value = this._angleSliderElement.value = this._gradient.angleValue;

        this.dispatchEventToListeners(WI.GradientEditor.Event.GradientChanged, {gradient: this._gradient});
    }
};

WI.GradientEditor.Event = {
    GradientChanged: "gradient-editor-gradient-changed",
    ColorPickerToggled: "gradient-editor-color-picker-toggled"
};
