/*
 * Copyright (C) 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.
 *
 * 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.
 */

WebInspector.VisualStyleNumberInputBox = class VisualStyleNumberInputBox extends WebInspector.VisualStylePropertyEditor
{
    constructor(propertyNames, text, possibleValues, possibleUnits, allowNegativeValues, layoutReversed)
    {
        let unitlessNumberUnit = WebInspector.UIString("Number");

        super(propertyNames, text, possibleValues, possibleUnits || [unitlessNumberUnit], "number-input-box", layoutReversed);

        this._unitlessNumberUnit = unitlessNumberUnit;

        this._hasUnits = this._possibleUnits.basic.some((unit) => unit !== unitlessNumberUnit);
        this._allowNegativeValues = !!allowNegativeValues || false;

        this.contentElement.classList.toggle("no-values", !possibleValues || !possibleValues.length);
        this.contentElement.classList.toggle("no-units", !this._hasUnits);

        let focusRingElement = document.createElement("div");
        focusRingElement.classList.add("focus-ring");
        this.contentElement.appendChild(focusRingElement);

        this._keywordSelectElement = document.createElement("select");
        this._keywordSelectElement.classList.add("number-input-keyword-select");
        if (this._possibleUnits.advanced)
            this._keywordSelectElement.title = WebInspector.UIString("Option-click to show all units");

        this._unchangedOptionElement = document.createElement("option");
        this._unchangedOptionElement.value = "";
        this._unchangedOptionElement.text = WebInspector.UIString("Unchanged");
        this._keywordSelectElement.appendChild(this._unchangedOptionElement);

        this._keywordSelectElement.appendChild(document.createElement("hr"));

        if (this._possibleValues) {
            this._createValueOptions(this._possibleValues.basic);
            this._keywordSelectElement.appendChild(document.createElement("hr"));
        }

        if (this._possibleUnits)
            this._createUnitOptions(this._possibleUnits.basic);

        this._advancedUnitsElements = null;

        this._keywordSelectElement.addEventListener("focus", this._focusContentElement.bind(this));
        this._keywordSelectElement.addEventListener("mousedown", this._keywordSelectMouseDown.bind(this));
        this._keywordSelectElement.addEventListener("change", this._keywordChanged.bind(this));
        this._keywordSelectElement.addEventListener("blur", this._blurContentElement.bind(this));
        this.contentElement.appendChild(this._keywordSelectElement);

        this._numberUnitsContainer = document.createElement("div");
        this._numberUnitsContainer.classList.add("number-input-container");

        this._valueNumberInputElement = document.createElement("input");
        this._valueNumberInputElement.classList.add("number-input-value");
        this._valueNumberInputElement.spellcheck = false;
        this._valueNumberInputElement.addEventListener("focus", this._focusContentElement.bind(this));
        this._valueNumberInputElement.addEventListener("keydown", this._valueNumberInputKeyDown.bind(this));
        this._valueNumberInputElement.addEventListener("keyup", this.debounce(250)._valueNumberInputKeyUp);
        this._valueNumberInputElement.addEventListener("blur", this._blurContentElement.bind(this));
        this._valueNumberInputElement.addEventListener("change", this.debounce(250)._valueNumberInputChanged);
        this._numberUnitsContainer.appendChild(this._valueNumberInputElement);

        this._unitsElement = document.createElement("span");
        this._numberUnitsContainer.appendChild(this._unitsElement);

        this.contentElement.appendChild(this._numberUnitsContainer);

        this._setNumberInputIsEditable(true);
        this._valueNumberInputElement.value = null;
        this._valueNumberInputElement.setAttribute("placeholder", 0);
        this._unitsElementTextContent = this._keywordSelectElement.value = this.valueIsSupportedUnit("px") ? "px" : this._possibleUnits.basic[0];
    }

    // Public

    get value()
    {
        if (this._numberInputIsEditable)
            return parseFloat(this._valueNumberInputElement.value);
        return this._keywordSelectElement.value || null;
    }

    set value(value)
    {
        if (value && value === this.value)
            return;

        if (this._propertyMissing) {
            if (value || this._updatedValues.placeholder)
                this.specialPropertyPlaceholderElement.textContent = (value || this._updatedValues.placeholder) + (this._updatedValues.units || "");

            if (isNaN(value)) {
                this._unchangedOptionElement.selected = true;
                this._setNumberInputIsEditable();
                this.specialPropertyPlaceholderElement.hidden = false;
                return;
            }
        }

        this.specialPropertyPlaceholderElement.hidden = true;

        if (!value) {
            this._valueNumberInputElement.value = null;
            this._markUnitsContainerIfInputHasValue();
            return;
        }

        if (!isNaN(value)) {
            this._setNumberInputIsEditable(true);
            this._valueNumberInputElement.value = Math.round(value * 100) / 100;
            this._markUnitsContainerIfInputHasValue();
            return;
        }

        if (this.valueIsSupportedKeyword(value)) {
            this._setNumberInputIsEditable();
            this._keywordSelectElement.value = value;
            return;
        }
    }

    get units()
    {
        if (this._unchangedOptionElement.selected)
            return null;

        let keyword = this._keywordSelectElement.value;
        if (!this.valueIsSupportedUnit(keyword))
            return null;

        return keyword;
    }

    set units(unit)
    {
        if (this._unchangedOptionElement.selected || unit === this.units)
            return;

        if (!unit && !this._possibleUnits.basic.includes(this._unitlessNumberUnit) && !this.valueIsSupportedUnit(unit))
            return;

        if (this._valueIsSupportedAdvancedUnit(unit))
            this._addAdvancedUnits();

        this._setNumberInputIsEditable(true);
        this._keywordSelectElement.value = unit || this._unitlessNumberUnit;
        this._unitsElementTextContent = unit;
    }

    get placeholder()
    {
        return this._valueNumberInputElement.getAttribute("placeholder");
    }

    set placeholder(text)
    {
        if (text === this.placeholder)
            return;

        let onlyNumericalText = text && !isNaN(text) && (Math.round(text * 100) / 100);
        this._valueNumberInputElement.setAttribute("placeholder", onlyNumericalText || 0);

        if (!onlyNumericalText)
            this.specialPropertyPlaceholderElement.textContent = this._canonicalizedKeywordForKey(text) || text;
    }

    get synthesizedValue()
    {
        if (this._unchangedOptionElement.selected)
            return null;

        let value = this._valueNumberInputElement.value;
        if (this._numberInputIsEditable && !value)
            return null;

        let keyword = this._keywordSelectElement.value;
        return this.valueIsSupportedUnit(keyword) ? value + (keyword === this._unitlessNumberUnit ? "" : keyword) : keyword;
    }

    updateValueFromText(text, value)
    {
        let match = this.parseValue(value);
        this.value = match ? match[1] : value;
        this.units = match ? match[2] : null;
        return this.modifyPropertyText(text, value);
    }

    // Protected

    set specialPropertyPlaceholderElementText(text)
    {
        this._unchangedOptionElement.selected = true;

        super.specialPropertyPlaceholderElementText = text;
    }

    parseValue(text)
    {
        return /^(-?[\d.]+)([^\s\d]{0,4})(?:\s*;?)$/.exec(text);
    }

    // Private

    set _unitsElementTextContent(text)
    {
        if (!this._hasUnits)
            return;

        this._unitsElement.textContent = text === this._unitlessNumberUnit ? "" : text;
        this._markUnitsContainerIfInputHasValue();
    }

    _setNumberInputIsEditable(flag)
    {
        this._numberInputIsEditable = flag || false;
        this.contentElement.classList.toggle("number-input-editable", this._numberInputIsEditable);
    }

    _markUnitsContainerIfInputHasValue()
    {
        let numberInputValue = this._valueNumberInputElement.value;
        this._numberUnitsContainer.classList.toggle("has-value", numberInputValue && numberInputValue.length);
    }

    _keywordChanged()
    {
        let unchangedOptionSelected = this._unchangedOptionElement.selected;
        if (!unchangedOptionSelected) {
            let selectedKeywordIsUnit = this.valueIsSupportedUnit(this._keywordSelectElement.value);
            if (!this._numberInputIsEditable && selectedKeywordIsUnit)
                this._valueNumberInputElement.value = null;

            this._unitsElementTextContent = this._keywordSelectElement.value;
            this._setNumberInputIsEditable(selectedKeywordIsUnit);
        } else
            this._setNumberInputIsEditable(false);

        this._valueDidChange();
        this.specialPropertyPlaceholderElement.hidden = !unchangedOptionSelected;
    }

    _valueNumberInputKeyDown(event)
    {
        if (!this._numberInputIsEditable)
            return;

        function adjustValue(delta)
        {
            let newValue;
            let value = this.value;
            if (!value && isNaN(value)) {
                let placeholderValue = this.placeholder && !isNaN(this.placeholder) ? parseFloat(this.placeholder) : 0;
                newValue = placeholderValue + delta;
            } else
                newValue = value + delta;

            if (!this._allowNegativeValues && newValue < 0)
                newValue = 0;

            this._propertyMissing = false;
            this.value = Math.round(newValue * 100) / 100;
            this._valueDidChange();
        }

        let shift = 1;
        if (event.ctrlKey)
            shift /= 10;
        else if (event.shiftKey)
            shift *= 10;

        let key = event.keyIdentifier;
        if (key.startsWith("Page"))
            shift *= 10;

        if (key === "Up" || key === "PageUp") {
            event.preventDefault();
            adjustValue.call(this, shift);
            return;
        }

        if (key === "Down" || key === "PageDown") {
            event.preventDefault();
            adjustValue.call(this, -shift);
            return;
        }

        this._markUnitsContainerIfInputHasValue();
        this.debounce(250)._valueDidChange();
    }

    _valueNumberInputKeyUp(event)
    {
        if (!this._numberInputIsEditable)
            return;

        this._markUnitsContainerIfInputHasValue();
        this._valueDidChange();
    }

    _keywordSelectMouseDown(event)
    {
        if (event.altKey)
            this._addAdvancedUnits();
        else if (!this._valueIsSupportedAdvancedUnit(this._keywordSelectElement.value))
            this._removeAdvancedUnits();
    }

    _createValueOptions(values)
    {
        let addedElements = [];
        for (let key in values) {
            let option = document.createElement("option");
            option.value = key;
            option.text = values[key];
            this._keywordSelectElement.appendChild(option);
            addedElements.push(option);
        }

        return addedElements;
    }

    _createUnitOptions(units)
    {
        let addedElements = [];
        for (let unit of units) {
            let option = document.createElement("option");
            option.text = unit;
            this._keywordSelectElement.appendChild(option);
            addedElements.push(option);
        }

        return addedElements;
    }

    _addAdvancedUnits()
    {
        if (this._advancedUnitsElements)
            return;

        this._keywordSelectElement.appendChild(document.createElement("hr"));
        this._advancedUnitsElements = this._createUnitOptions(this._possibleUnits.advanced);
    }

    _removeAdvancedUnits()
    {
        if (!this._advancedUnitsElements)
            return;

        this._keywordSelectElement.removeChild(this._advancedUnitsElements[0].previousSibling);
        for (let element of this._advancedUnitsElements)
            this._keywordSelectElement.removeChild(element);

        this._advancedUnitsElements = null;
    }

    _focusContentElement(event)
    {
        this.contentElement.classList.add("focused");
    }

    _blurContentElement(event)
    {
        this.contentElement.classList.remove("focused");
    }

    _valueNumberInputChanged(event)
    {
        let newValue = this.value;
        if (!newValue && isNaN(newValue))
            newValue = this.placeholder && !isNaN(this.placeholder) ? parseFloat(this.placeholder) : 0;

        if (!this._allowNegativeValues && newValue < 0)
            newValue = 0;

        this.value = Math.round(newValue * 100) / 100;
        this._valueDidChange();
    }

    _toggleTabbingOfSelectableElements(disabled)
    {
        this._keywordSelectElement.tabIndex = disabled ? "-1" : null;
        this._valueNumberInputElement.tabIndex = disabled ? "-1" : null;
    }
};
