import { BaseXform } from "../base-xform.js";
import { ColorXform } from "./color-xform.js";
class StopXform extends BaseXform {
    constructor() {
        super();
        this.map = {
            color: new ColorXform()
        };
    }
    get tag() {
        return "stop";
    }
    render(xmlStream, model) {
        xmlStream.openNode("stop");
        xmlStream.addAttribute("position", model.position);
        this.map.color.render(xmlStream, model.color);
        xmlStream.closeNode();
    }
    parseOpen(node) {
        if (this.parser) {
            this.parser.parseOpen(node);
            return true;
        }
        switch (node.name) {
            case "stop":
                this.model = {
                    position: parseFloat(node.attributes.position)
                };
                return true;
            case "color":
                this.parser = this.map.color;
                this.parser.parseOpen(node);
                return true;
            default:
                return false;
        }
    }
    parseText() { }
    parseClose(name) {
        if (this.parser) {
            if (!this.parser.parseClose(name)) {
                this.model.color = this.parser.model;
                this.parser = undefined;
            }
            return true;
        }
        return false;
    }
}
class PatternFillXform extends BaseXform {
    constructor() {
        super();
        this.map = {
            fgColor: new ColorXform("fgColor"),
            bgColor: new ColorXform("bgColor")
        };
    }
    get name() {
        return "pattern";
    }
    get tag() {
        return "patternFill";
    }
    render(xmlStream, model) {
        xmlStream.openNode("patternFill");
        xmlStream.addAttribute("patternType", model.pattern);
        if (model.fgColor) {
            this.map.fgColor.render(xmlStream, model.fgColor);
        }
        if (model.bgColor) {
            this.map.bgColor.render(xmlStream, model.bgColor);
        }
        xmlStream.closeNode();
    }
    parseOpen(node) {
        if (this.parser) {
            this.parser.parseOpen(node);
            return true;
        }
        switch (node.name) {
            case "patternFill":
                this.model = {
                    type: "pattern",
                    pattern: node.attributes.patternType
                };
                return true;
            default:
                this.parser = this.map[node.name];
                if (this.parser) {
                    this.parser.parseOpen(node);
                    return true;
                }
                return false;
        }
    }
    parseText(text) {
        if (this.parser) {
            this.parser.parseText(text);
        }
    }
    parseClose(name) {
        if (this.parser) {
            if (!this.parser.parseClose(name)) {
                if (this.parser.model) {
                    this.model[name] = this.parser.model;
                }
                this.parser = undefined;
            }
            return true;
        }
        return false;
    }
}
class GradientFillXform extends BaseXform {
    constructor() {
        super();
        this.map = {
            stop: new StopXform()
        };
    }
    get name() {
        return "gradient";
    }
    get tag() {
        return "gradientFill";
    }
    render(xmlStream, model) {
        xmlStream.openNode("gradientFill");
        switch (model.gradient) {
            case "angle":
                xmlStream.addAttribute("degree", model.degree);
                break;
            case "path":
                xmlStream.addAttribute("type", "path");
                if (model.center.left) {
                    xmlStream.addAttribute("left", model.center.left);
                    if (model.center.right === undefined) {
                        xmlStream.addAttribute("right", model.center.left);
                    }
                }
                if (model.center.right) {
                    xmlStream.addAttribute("right", model.center.right);
                }
                if (model.center.top) {
                    xmlStream.addAttribute("top", model.center.top);
                    if (model.center.bottom === undefined) {
                        xmlStream.addAttribute("bottom", model.center.top);
                    }
                }
                if (model.center.bottom) {
                    xmlStream.addAttribute("bottom", model.center.bottom);
                }
                break;
            default:
                break;
        }
        const stopXform = this.map.stop;
        model.stops.forEach(stopModel => {
            stopXform.render(xmlStream, stopModel);
        });
        xmlStream.closeNode();
    }
    parseOpen(node) {
        if (this.parser) {
            this.parser.parseOpen(node);
            return true;
        }
        switch (node.name) {
            case "gradientFill": {
                const model = (this.model = {
                    stops: []
                });
                if (node.attributes.degree) {
                    model.gradient = "angle";
                    model.degree = parseInt(node.attributes.degree, 10);
                }
                else if (node.attributes.type === "path") {
                    model.gradient = "path";
                    model.center = {
                        left: node.attributes.left ? parseFloat(node.attributes.left) : 0,
                        top: node.attributes.top ? parseFloat(node.attributes.top) : 0
                    };
                    if (node.attributes.right !== node.attributes.left) {
                        model.center.right = node.attributes.right ? parseFloat(node.attributes.right) : 0;
                    }
                    if (node.attributes.bottom !== node.attributes.top) {
                        model.center.bottom = node.attributes.bottom ? parseFloat(node.attributes.bottom) : 0;
                    }
                }
                return true;
            }
            case "stop":
                this.parser = this.map.stop;
                this.parser.parseOpen(node);
                return true;
            default:
                return false;
        }
    }
    parseText(text) {
        if (this.parser) {
            this.parser.parseText(text);
        }
    }
    parseClose(name) {
        if (this.parser) {
            if (!this.parser.parseClose(name)) {
                this.model.stops.push(this.parser.model);
                this.parser = undefined;
            }
            return true;
        }
        return false;
    }
}
// Fill encapsulates translation from fill model to/from xlsx
class FillXform extends BaseXform {
    constructor() {
        super();
        this.map = {
            patternFill: new PatternFillXform(),
            gradientFill: new GradientFillXform()
        };
    }
    get tag() {
        return "fill";
    }
    render(xmlStream, model) {
        xmlStream.addRollback();
        xmlStream.openNode("fill");
        switch (model.type) {
            case "pattern":
                this.map.patternFill.render(xmlStream, model);
                break;
            case "gradient":
                this.map.gradientFill.render(xmlStream, model);
                break;
            default:
                xmlStream.rollback();
                return;
        }
        xmlStream.closeNode();
        xmlStream.commit();
    }
    parseOpen(node) {
        if (this.parser) {
            this.parser.parseOpen(node);
            return true;
        }
        switch (node.name) {
            case "fill":
                this.model = {};
                return true;
            default:
                this.parser = this.map[node.name];
                if (this.parser) {
                    this.parser.parseOpen(node);
                    return true;
                }
                return false;
        }
    }
    parseText(text) {
        if (this.parser) {
            this.parser.parseText(text);
        }
    }
    parseClose(name) {
        if (this.parser) {
            if (!this.parser.parseClose(name)) {
                this.model = this.parser.model;
                this.model.type = this.parser.name;
                this.parser = undefined;
            }
            return true;
        }
        return false;
    }
    validStyle(value) {
        return FillXform.validPatternValues[value];
    }
}
FillXform.validPatternValues = [
    "none",
    "solid",
    "darkVertical",
    "darkGray",
    "mediumGray",
    "lightGray",
    "gray125",
    "gray0625",
    "darkHorizontal",
    "darkVertical",
    "darkDown",
    "darkUp",
    "darkGrid",
    "darkTrellis",
    "lightHorizontal",
    "lightVertical",
    "lightDown",
    "lightUp",
    "lightGrid",
    "lightTrellis",
    "lightGrid"
].reduce((p, v) => {
    p[v] = true;
    return p;
}, {});
FillXform.StopXform = StopXform;
FillXform.PatternFillXform = PatternFillXform;
FillXform.GradientFillXform = GradientFillXform;
export { FillXform };
