/* global Bdf,$$,Intl */

Bdf.Cell = function (text, value, cssClasses) {
    this.text = text;
    this.value = value;
    this.cssClasses = cssClasses;
    this.data = {};
    if ((value) || (value === "")) {
        this.data["value"] = value;
    }
    this.withLink = false;
    this.linkData = {};
};

Bdf.Cell.prototype.setData = function (key, value) {
    this.data[key] = value;
};

Bdf.Cell.prototype.setLinkData = function (key, value) {
    this.withLink = true;
    this.linkData[key] = value;
};

Bdf.Cell.prototype.addClass = function (className) {
    if (!this.cssClasses) {
        this.cssClasses = className;
    } else {
        this.cssClasses = this.cssClasses + " " + className;
    }
};

Bdf.Cell.Engine = function(settings) {
    this.lang = null;
    this.classes = {
        number: "global-cell-Number",
        amount: "global-cell-Number",
        date: "global-cell-Number"
    };
    if (settings) {
        if (settings.lang) {
            this.lang = settings.lang;
        }
        if (settings.classes) {
            for(let propKey in settings.classes) {
                this.classes[propKey] = settings.classes[propKey];
            }
        }
    }
    
};

Bdf.Cell.Engine.prototype.convert = function (obj, context) {
    var engine = this;
    var objType = typeof obj;
    switch(objType) {
        case "string":
            return new Bdf.Cell(obj);
        case "object":
            if (!obj) {
                return _empty();
            } else if (Array.isArray(obj)) {
                return _fromArray(obj);
            } else {
                return this.convertObject(obj, context);
            }
        case "number":
            return new Bdf.Cell(obj.toString(), obj, this.classes.number);
        case "boolean":
            if (obj) {
                return new Bdf.Cell("X");
            } else {
                return _empty();
            }
        case "undefined":
            return _empty();
        case "bigint":
        case "symbol":
        case "function":
        default:
            return new Bdf.Cell(obj.toString());
    }
    
    function _fromArray(array) {
        let text = "";
        for(let item of array) {
            let itemCell = engine.convert(item, context);
            if (itemCell.text.length > 0) {
                if (text.length > 0) {
                    text = text + " | ";
                }
                text = text + itemCell.text;
            }
        }
        return new Bdf.Cell(text);
    }
    
    function _empty() {
        return new Bdf.Cell("");
    }

};

Bdf.Cell.Engine.prototype.convertObject = function (obj, context) {
    if (!obj.hasOwnProperty("type")) {
        return _keepJson();
    }
    var cell = null;
    switch(obj.type) {
        case "amount":
            cell = this.buildAmountCell(obj);
            break;
        case "date":
            cell = this.buildDateCell(obj, context);
            break;
        case "number":
            cell = this.buildNumberCell(obj);
            break;
    }
    if (!cell) {
        return _keepJson();
    } 
    return cell;
    
    function _keepJson() {
        return new Bdf.Cell(JSON.stringify(obj));
    }
};

Bdf.Cell.Engine.prototype.buildCell = function (obj, text, value) {
    if (!text) {
        if (value === null) {
            return null;
        } else {
            text = JSON.stringify(obj);
        }
    }
    var cssClasses = "";
    if (this.classes.hasOwnProperty(obj.type)) {
        cssClasses = this.classes[obj.type];
    }
    return new Bdf.Cell(text, value, cssClasses);
};

Bdf.Cell.Engine.prototype.buildAmountCell = function (obj) {
    var text = this.getLabel(obj);
    if (!text) {
        text = _buildAmountLabel();
    }
    var value = this.getPropertyValue(obj, ["long", "decimal"]);
    return this.buildCell(obj, text, value);

    
    function _buildAmountLabel() {
        if (obj.hasOwnProperty("code")) {
            return obj["code"];
        }
        if (!obj.hasOwnProperty("currency")) {
            return null;
        }
        if (obj.hasOwnProperty("decimal")) {
            return obj["decimal"] + " " + obj["currency"];
        } else {
            return null;
        }
    }
};

Bdf.Cell.Engine.prototype.buildDateCell = function (obj, context) {
    var engine = this;
    var text = _format();
    if (!text) {
        text = this.getLabel(obj);
    }
    if (!text) {
        text = this.getPropertyValue(obj, ["code", "iso"]);
    }
    var value = this.getPropertyValue(obj, ["iso", "code"]);
    return this.buildCell(obj, text, value);
    
    function _format() {
        let dateFormatter;
        if ((context) && (context.dateFormatter)) {
            dateFormatter = context.dateFormatter;
        } else {
            return null;
        }
        if (obj.hasOwnProperty("datetype")) {
            let value = engine.getPropertyValue(obj, ["code", "iso"]);
            if (value) {
                return dateFormatter.format(obj.datetype, value);
            } else {
                return null;
            }
        } else if (obj.hasOwnProperty("iso")) {
            return dateFormatter.format("day", engine.getPropertyValue(obj, "iso"));
        }
        return null;
    }
};

Bdf.Cell.Engine.prototype.buildNumberCell = function (obj) {
    var text = this.getLabel(obj);
    if (!text) {
        text = this.getPropertyValue(obj, ["code", "value"]);
    }
    var value = this.getPropertyValue(obj, ["code", "value"]);
    return this.buildCell(obj, text, value);
};

Bdf.Cell.Engine.prototype.getPropertyName = function (obj, array) {
    if (typeof array === "string") {
        if (obj.hasOwnProperty(array)) {
            return array;
        } else {
            return null;
        }
    }
    for(let propName of array) {
        if (obj.hasOwnProperty(propName)) {
            return propName;
        }
    }
    return null;
};

Bdf.Cell.Engine.prototype.getPropertyValue = function (obj, array) {
    if (typeof array === "string") {
        if (obj.hasOwnProperty(array)) {
            return obj[array];
        } else {
            return null;
        }
    }
    for(let propName of array) {
        if (obj.hasOwnProperty(propName)) {
            return obj[propName];
        }
    }
    return null;
};

Bdf.Cell.Engine.prototype.getLabel = function (obj) {
    var propName = this.getPropertyName(obj, ["labels", "monthlabels"]);
    if (!propName) {
        return null;
    }
    if (this.lang) {
        if (obj[propName].hasOwnProperty(this.lang)) {
            return obj.labels[this.lang];
        }
    }
    for(let propName2 in obj[propName]) {
        return obj[propName][propName2];
    }
    return null;
};

Bdf.Cell.toDayFormatter = function (dateFormat) {
    return function (dateCode) {
        return dateFormat.format(new Date(dateCode));
    };
};

Bdf.Cell.ShortMonthFormatter = function (monthCode) {
    return monthCode.substring(5,7) + "/" + monthCode.substring(0,4);
};

Bdf.Cell.DateFormatter = function (locale, dateStyle) {
    this.day = new Intl.DateTimeFormat(locale, {dateStyle: dateStyle});
    this.month = new Intl.DateTimeFormat(locale, {month: _getMonth(), year: "numeric"});
            
    function _getMonth() {
        switch(dateStyle) {
            case "short":
                return "2-digit";
            case "medium":
                return "short";
            default:
                return "long";
        }
    }
};

Bdf.Cell.DateFormatter.prototype.format = function (dateType, value) {
    var formatter = this;
    switch(dateType) {
        case "day":
            return formatter.day.format(new Date(value));
        case "month":
            let date = new Date(parseInt(value.substring(0,4)), parseInt(value.substring(5,7)) - 1);
            return formatter.month.format(date);
        case "year":
            if (value.length > 4) {
                return value.substring(0, 4);
            } else {
                return value;
            }
        default:
            return value;
    }
};

