/* global OpenDocument */

/***********************************************************
 * 
 * @constructor
 * @param {String} type
 * @param {String} styleName
 * @returns {OpenDocument.Style}
 */
OpenDocument.Style = function (type, styleName) {
    this.type = type;
    this.styleName = styleName;
    this.styleFamily = OpenDocument.Style.getMatchingStyleFamily(type);
    this.parentStyleName = "";
    this.dataStyleName = "";
    this.propertiesMaps = new Map([
        ["paragraph", new Map()],
        ["text", new Map()],
        ["table-cell", new Map()],
        ["table-row", new Map()],
        ["table-column", new Map()]
    ]);
};

OpenDocument.Style.prototype.putStyleProperty = function (stylePropertyDef, value) {
    var propertyName = stylePropertyDef.name;
    switch(stylePropertyDef.format) {
        case "color":
            value = OpenDocument.Style.formatColor(value);
            break;
        case "wrap":
            value = _convertWrap();
            break;
    }
    var property = {
        name: propertyName,
        value: value
    };
    this.propertiesMaps.get(stylePropertyDef.category).set(propertyName, property);
    
    function _convertWrap() {
        switch(value) {
            case "anywhere":
            case "break-word":
                return "wrap";
            default:
                return "no-wrap";
        }
    }
};

OpenDocument.Style.prototype.setParent = function (parentStyleName) {
    this.parentStyleName = parentStyleName;
};

OpenDocument.Style.prototype.setDataStyle = function (dataStyleName) {
    this.dataStyleName = dataStyleName;
};

OpenDocument.Style.prototype.isEmpty = function () {
    for(let map of this.propertiesMaps.values()) {
        if (map.size > 0) {
            return false;
        }
    }  
    return true;
};

OpenDocument.Style.prototype.copyProperties = function (otherStyle) {
    if (otherStyle.parentStyleName) {
        this.setParent(otherStyle.parentStyleName);
    }
    for(let entry of otherStyle.propertiesMaps) {
        let otherMap = entry[1];
        let thisMap = this.propertiesMaps.get(entry[0]);
        for(let entry2 of otherMap) {
            thisMap.set(entry2[0], entry2[1]);
        }
    }
};

/**
 * 
 * @param {OpenDocument.XmlWriter} xmlWriter
 * @returns {undefined}
 */
OpenDocument.Style.prototype.write = function (xmlWriter) {
    xmlWriter
            .startStyleOpenTag(this.styleName, this.styleFamily, this.parentStyleName)
            .addAttribute("style:data-style-name", this.dataStyleName);
    if (this.isEmpty()) {
        xmlWriter
            .closeEmptyTag();
    } else {
        xmlWriter
            .endOpenTag();
        for(let entry of this.propertiesMaps) {
            let category = entry[0];
            let map = entry[1];
            if (map.size > 0) {
                xmlWriter
                        .startOpenTag("style:" + category + "-properties");
                for(let property of map.values()) {
                    xmlWriter
                            .addAttribute(property.name, property.value);
                }
                xmlWriter
                        .closeEmptyTag();
            }
        }
        xmlWriter
                .closeStyle();
    }
};

OpenDocument.Style.getStylePropertyDef = function (type, name) {
    name = _checkAlias();
    if (OpenDocument.Style.STYLEPROPERTYDEFS.hasOwnProperty(name)) {
        let propertyDef = OpenDocument.Style.STYLEPROPERTYDEFS[name];
        if (propertyDef.categories) {
            for(let propKey in propertyDef.categories) {
                if (propKey === type) {
                    return Object.assign({}, propertyDef, {category: propertyDef.categories[propKey]});
                }
            }
            return null;
        } else {
            return propertyDef;
        }
    } else {
        return null;
    }
    
    function _checkAlias() {
        switch(type) {
            case "row":
                switch(name) {
                    case "height":
                        return "row-height";
                }
                break;
            case "column":
                switch(name) {
                    case "width":
                        return "column-width";
                }
                break;
            case "cell":
                switch(name) {
                    case "overflow-wrap":
                        return "wrap-option";
                }
                break;
        }
        return name;
    }

};

OpenDocument.Style.getMatchingStyleFamily = function (type) {
    switch(type) {
        case "cell":
            return "table-cell";
        case "row":
            return "table-row";
        case "column":
            return "table-column";
    }
};

OpenDocument.Style.STYLEPROPERTYDEFS = {
    "background-color": {
        name: "fo:background-color",
        categories: {
            "cell": "table-cell",
            "row": "table-row"
        },
        format: "color"
    },
    "border": {
        name: "fo:border",
        category: "table-cell"
    },
    "border-bottom": {
        name: "fo:border-bottom",
        category: "table-cell"
    },
    "border-left": {
        name: "fo:border-left",
        category: "table-cell"
    },
    "border-right": {
        name: "fo:border-right",
        category: "table-cell"
    },
    "border-top": {
        name: "fo:border-top",
        category: "table-cell"
    },
    "color": {
        name: "fo:color",
        category: "text",
        format: "color"
    },
    "column-width": {
        name: "style:column-width",
        category: "table-column"
    },
    "font-size": {
        name: "fo:font-size",
        category: "text"
    },
    "font-style": {
        name: "fo:font-style",
        category: "text"
    },
    "font-weight": {
        name: "fo:font-weight",
        category: "text"
    },
    "padding": {
        name: "fo:padding",
        category: "table-cell"
    },
    "padding-bottom": {
        name: "fo:padding-bottom",
        category: "table-cell"
    },
    "padding-left": {
        name: "fo:padding-left",
        category: "table-cell"
    },
    "padding-right": {
        name: "fo:padding-right",
        category: "table-cell"
    },
    "padding-top": {
        name: "fo:padding-top",
        category: "table-cell"
    },
    "row-height": {
        name: "style:row-height",
        category: "table-row"
    },
    "text-align": {
        name: "fo:text-align",
        category: "paragraph"
    },
    "use-optimal-row-height": {
        name: "style:use-optimal-row-height",
        category: "table-row"
    },
    "vertical-align": {
        name: "style:vertical-align",
        category: "table-cell"
    },
    "wrap-option": {
        name: "fo:wrap-option",
        category: "table-cell",
        format: "wrap"
    }
};


OpenDocument.Style.formatColor = function (color) {
    let colorList = color.match(/rgb\((.*)\)/);
    if (colorList) {
        let hexresult = "#";
        for(let token of colorList[1].split(",")) {
            let hex = Number.parseInt(token.trim(), 10).toString(16);
            if (hex.length === 1) {
                hex = "0" + hex;
            }
            hexresult += hex;
        }
        color = hexresult;
    }
    return color;
};
