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

WI.Gradient = class Gradient
{
    constructor(type, stops)
    {
        this.type = type;
        this.stops = stops;
    }

    // Static

    static fromString(cssString)
    {
        var type;
        var openingParenthesisIndex = cssString.indexOf("(");
        var typeString = cssString.substring(0, openingParenthesisIndex);
        if (typeString.indexOf(WI.Gradient.Types.Linear) !== -1)
            type = WI.Gradient.Types.Linear;
        else if (typeString.indexOf(WI.Gradient.Types.Radial) !== -1)
            type = WI.Gradient.Types.Radial;
        else
            return null;

        var components = [];
        var currentParams = [];
        var currentParam = "";
        var openParentheses = 0;
        var ch = openingParenthesisIndex + 1;
        var c = null;
        while (c = cssString[ch]) {
            if (c === "(")
                openParentheses++;
            if (c === ")")
                openParentheses--;

            var isComma = c === ",";
            var isSpace = /\s/.test(c);

            if (openParentheses === 0) {
                if (isSpace) {
                    if (currentParam !== "")
                        currentParams.push(currentParam);
                    currentParam = "";
                } else if (isComma) {
                    currentParams.push(currentParam);
                    components.push(currentParams);
                    currentParams = [];
                    currentParam = "";
                }
            }

            if (openParentheses === -1) {
                currentParams.push(currentParam);
                components.push(currentParams);
                break;
            }

            if (openParentheses > 0 || (!isComma && !isSpace))
                currentParam += c;

            ch++;
        }

        if (openParentheses !== -1)
            return null;

        var gradient;
        if (type === WI.Gradient.Types.Linear)
            gradient = WI.LinearGradient.fromComponents(components);
        else
            gradient = WI.RadialGradient.fromComponents(components);

        if (gradient)
            gradient.repeats = typeString.startsWith("repeating");

        return gradient;
    }

    static stopsWithComponents(components)
    {
        // FIXME: handle lengths.
        var stops = components.map(function(component) {
            while (component.length) {
                var color = WI.Color.fromString(component.shift());
                if (!color)
                    continue;

                var stop = {color};
                if (component.length && component[0].substr(-1) === "%")
                    stop.offset = parseFloat(component.shift()) / 100;
                return stop;
            }
        });

        if (!stops.length)
            return null;

        for (var i = 0, count = stops.length; i < count; ++i) {
            var stop = stops[i];

            // If one of the stops failed to parse, then this is not a valid
            // set of components for a gradient. So the whole thing is invalid.
            if (!stop)
                return null;

            if (!stop.offset)
                stop.offset = i / (count - 1);
        }

        return stops;
    }

    // Public

    stringFromStops(stops)
    {
        var count = stops.length - 1;
        return stops.map(function(stop, index) {
            var str = stop.color;
            if (stop.offset !== index / count)
                str += " " + Math.round(stop.offset * 10_000) / 100 + "%";
            return str;
        }).join(", ");
    }

    // Public

    copy()
    {
        // Implemented by subclasses.
    }

    toString()
    {
        // Implemented by subclasses.
    }
};

WI.Gradient.Types = {
    Linear: "linear-gradient",
    Radial: "radial-gradient"
};

WI.LinearGradient = class LinearGradient extends WI.Gradient
{
    constructor(angle, stops)
    {
        super(WI.Gradient.Types.Linear, stops);
        this._angle = angle;
    }

    // Static

    static fromComponents(components)
    {
        let angle = {value: 180, units: WI.LinearGradient.AngleUnits.DEG};

        if (components[0].length === 1 && !WI.Color.fromString(components[0][0])) {
            let match = components[0][0].match(/([-\d\.]+)(\w+)/);
            if (!match || !Object.values(WI.LinearGradient.AngleUnits).includes(match[2]))
                return null;

            angle.value = parseFloat(match[1]);
            angle.units = match[2];

            components.shift();
        } else if (components[0][0] === "to") {
            components[0].shift();
            switch (components[0].sort().join(" ")) {
            case "top":
                angle.value = 0;
                break;
            case "right top":
                angle.value = 45;
                break;
            case "right":
                angle.value = 90;
                break;
            case "bottom right":
                angle.value = 135;
                break;
            case "bottom":
                angle.value = 180;
                break;
            case "bottom left":
                angle.value = 225;
                break;
            case "left":
                angle.value = 270;
                break;
            case "left top":
                angle.value = 315;
                break;
            default:
                return null;
            }

            components.shift();
        } else if (components[0].length !== 1 && !WI.Color.fromString(components[0][0])) {
            // If the first component is not a color, then we're dealing with a
            // legacy linear gradient format that we don't support.
            return null;
        }

        var stops = WI.Gradient.stopsWithComponents(components);
        if (!stops)
            return null;

        return new WI.LinearGradient(angle, stops);
    }

    // Public

    set angleValue(value) { this._angle.value = value; }

    get angleValue()
    {
        return this._angle.value.maxDecimals(2);
    }

    set angleUnits(units)
    {
        if (units === this._angle.units)
            return;

        this._angle.value = this._angleValueForUnits(units);
        this._angle.units = units;
    }

    get angleUnits() { return this._angle.units; }

    copy()
    {
        return new WI.LinearGradient(this._angle, this.stops.concat());
    }

    toString()
    {
        let str = "";

        let deg = this._angleValueForUnits(WI.LinearGradient.AngleUnits.DEG);
        if (deg === 0)
            str += "to top";
        else if (deg === 45)
            str += "to top right";
        else if (deg === 90)
            str += "to right";
        else if (deg === 135)
            str += "to bottom right";
        else if (deg === 225)
            str += "to bottom left";
        else if (deg === 270)
            str += "to left";
        else if (deg === 315)
            str += "to top left";
        else if (deg !== 180)
            str += this.angleValue + this.angleUnits;

        if (str !== "")
            str += ", ";

        str += this.stringFromStops(this.stops);

        return (this.repeats ? "repeating-" : "") + this.type + "(" + str + ")";
    }

    // Private

    _angleValueForUnits(units)
    {
        if (units === this._angle.units)
            return this._angle.value;

        let deg = 0;

        switch (this._angle.units) {
        case WI.LinearGradient.AngleUnits.DEG:
            deg = this._angle.value;
            break;

        case WI.LinearGradient.AngleUnits.RAD:
            deg = this._angle.value * 180 / Math.PI;
            break;

        case WI.LinearGradient.AngleUnits.GRAD:
            deg = this._angle.value / 400 * 360;
            break;

        case WI.LinearGradient.AngleUnits.TURN:
            deg = this._angle.value * 360;
            break;

        default:
            WI.reportInternalError(`Unknown angle units "${this._angle.units}"`);
            return 0;
        }

        let value = 0;

        switch (units) {
        case WI.LinearGradient.AngleUnits.DEG:
            value = deg;
            break;

        case WI.LinearGradient.AngleUnits.RAD:
            value = deg * Math.PI / 180;
            break;

        case WI.LinearGradient.AngleUnits.GRAD:
            value = deg / 360 * 400;
            break;

        case WI.LinearGradient.AngleUnits.TURN:
            value = deg / 360;
            break;
        }

        return value;
    }
};

WI.LinearGradient.AngleUnits = {
    DEG: "deg",
    RAD: "rad",
    GRAD: "grad",
    TURN: "turn",
};

WI.RadialGradient = class RadialGradient extends WI.Gradient
{
    constructor(sizing, stops)
    {
        super(WI.Gradient.Types.Radial, stops);
        this.sizing = sizing;
    }

    // Static

    static fromComponents(components)
    {
        var sizing = !WI.Color.fromString(components[0].join(" ")) ? components.shift().join(" ") : "";

        var stops = WI.Gradient.stopsWithComponents(components);
        if (!stops)
            return null;

        return new WI.RadialGradient(sizing, stops);
    }

    // Public

    copy()
    {
        return new WI.RadialGradient(this.sizing, this.stops.concat());
    }

    toString()
    {
        var str = this.sizing;

        if (str !== "")
            str += ", ";

        str += this.stringFromStops(this.stops);

        return (this.repeats ? "repeating-" : "") + this.type + "(" + str + ")";
    }
};
