/* global Bdf,$$,Intl,TableSheet */

TableSheet.CellFactory = function(settings) {
    this.lang = null;
    this.classes = {
        number: "tablesheet-cell-Number",
        amount: "tablesheet-cell-Number",
        date: "tablesheet-cell-Number"
    };
    this.textCut = 200;
    this.textThreshold = 350;
    if (settings) {
        for(let settingName in settings) {
            let settingValue = settings[settingName];
            switch(settingName) {
                case "lang":
                    this.lang = settingValue;
                    break;
                case "textCut":
                    this.textCut = settingValue;
                    break;
                case "textThreshold":
                    this.textThreshold = settingValue;
                    break;
                case "classes":
                    for(let propKey in settingValue) {
                        this.classes[propKey] = settings.classes[propKey];
                    }
                    break;
            }
        }
    }    
};

TableSheet.CellFactory.prototype.buildCell = function (cellSource, cellContext) {
    var cellFactory = this;
    var textCut = cellFactory.textCut;
    var textTreshold = cellFactory.textThreshold;
    if (cellContext) {
        if (cellContext.textCut) {
            textCut = cellContext.textCut;
        }
        if (cellContext.textTreshold) {
            textTreshold = cellContext.textTreshold;
        }
    }
    var objType = typeof cellSource;
    switch(objType) {
        case "string":
            return _fromString(cellSource);
        case "object":
            if (!cellSource) {
                return _empty();
            } else if (Array.isArray(cellSource)) {
                return _fromArray(cellSource);
            } else {
                return this.fromObject(cellSource, cellContext);
            }
        case "number":
            let numberCell = new TableSheet.Cell(cellSource.toString(), {
                    sortValue: cellSource,
                    cssClasses: this.classes.number
                });
            numberCell.setData("od-type", "number");
            return numberCell;
        case "boolean":
            if (cellSource) {
                return new TableSheet.Cell("X");
            } else {
                return _empty();
            }
        case "undefined":
            return _empty();
        case "bigint":
        case "symbol":
        case "function":
        default:
            return new TableSheet.Cell(cellSource.toString());
    }
    
    function _fromArray(array) {
        let text = "";
        for(let item of array) {
            let itemCell = cellFactory.buildCell(item, cellContext);
            if (itemCell.text.length > 0) {
                if (text.length > 0) {
                    text = text + " | ";
                }
                text = text + itemCell.text;
            }
        }
        return new TableSheet.Cell(text);
    }
    
    function _empty() {
        return new TableSheet.Cell("");
    }
    
    function _fromString(text) {
        let moreText = "";
        if (text.length > textCut) {
            if (text.length > textTreshold) {
                moreText = text.substring(textTreshold);
                text = text.substring(0, textTreshold);
            }
            let firstPart = text.substring(0, textCut);
            let secondPart = text.substring(textCut);
            let index = secondPart.indexOf('\n');
            if (index < 0) {
                index = secondPart.search(/[?!;:\.]\s/);
            }
            if (index < 0) {
                index = secondPart.lastIndexOf(' ');
            }
            if (index > -1) {
                moreText = secondPart.substring(index + 1) + moreText;
                secondPart = secondPart.substring(0, index + 1);
            }
            text = firstPart + secondPart;
        }
        if (moreText) {
            return new TableSheet.Cell(text, {
                moreText: moreText
            });
        } else {
            return new TableSheet.Cell(text);
        }
        
    }
};

TableSheet.CellFactory.prototype.fromObject = function (cellObject, cellContext) {
    var cellFactory = this;
    if (!cellObject.hasOwnProperty("type")) {
        return _keepJson();
    }
    var cell = null;
    switch(cellObject.type) {
        case "amount": {
            let text = cellFactory.getAmountText(cellObject);
            let value = cellFactory.getPropertyValue(cellObject, ["long", "decimal"]);
            cell = _buildTextCell(text, value);
            break;
        }
        case "date": {
            let text = cellFactory.getDateText(cellObject, cellContext);
            let value = cellFactory.getPropertyValue(cellObject, ["iso", "code"]);
            cell = _buildTextCell(text, value);
            cell.setData("od-type", "date");
            break;
        }
        case "item": {
            let text = cellFactory.getPropertyValue(cellObject, "value");
            cell = _buildTextCell(text, null);
            break;
        }
        case "link": {
            let text = cellFactory.getLinkText(cellObject);
            cell = _buildHtmlCell(text);
            break;
        }
        case "number": {
            let text = cellFactory.getNumberText(cellObject);
            let value = cellFactory.getPropertyValue(cellObject, ["code", "value"]);
            cell = _buildTextCell(text, value);
            cell.setData("od-type", "number");
            break;
        }
    }
    if (!cell) {
        return _keepJson();
    } 
    return cell;
    
    function _keepJson() {
        return new TableSheet.Cell(JSON.stringify(cellObject));
    }
    
    function _buildTextCell(text, value) {
        if (!text) {
            if (value === null) {
                return null;
            } else {
                text = JSON.stringify(cellObject);
            }
        }
        let cssClasses = "";
        if (cellFactory.classes.hasOwnProperty(cellObject.type)) {
            cssClasses = cellFactory.classes[cellObject.type];
        }
        return new TableSheet.Cell(text, {
                sortValue: value,
                cssClasses: cssClasses
            });
    }
    
    function _buildHtmlCell(text) {
        if (!text) {
            return null;
        }
        return new TableSheet.Cell(text, {
                isHtml: true
            });
    }
};

TableSheet.CellFactory.prototype.getAmountText = function (cellObject) {
    var text = this.getLabel(cellObject);
    if (!text) {
        text = _buildAmountLabel();
    }
    return text;
    
    function _buildAmountLabel() {
        if (cellObject.hasOwnProperty("code")) {
            return cellObject["code"];
        }
        if (!cellObject.hasOwnProperty("currency")) {
            return null;
        }
        if (cellObject.hasOwnProperty("decimal")) {
            return cellObject["decimal"] + " " + cellObject["currency"];
        } else {
            return null;
        }
    }
};

TableSheet.CellFactory.prototype.getDateText = function (cellObject, cellContext) {
    var cellFactory = this;
    var text = _format();
    if (!text) {
        text = this.getLabel(cellObject);
    }
    if (!text) {
        text = this.getPropertyValue(cellObject, ["code", "iso"]);
    }
    return text;
    
    function _format() {
        let dateFormatter;
        if ((cellContext) && (cellContext.dateFormatter)) {
            dateFormatter = cellContext.dateFormatter;
        } else {
            return null;
        }
        if (cellObject.hasOwnProperty("datetype")) {
            let value = cellFactory.getPropertyValue(cellObject, ["code", "iso"]);
            if (value) {
                return dateFormatter.format(cellObject.datetype, value);
            } else {
                return null;
            }
        } else if (cellObject.hasOwnProperty("iso")) {
            return dateFormatter.format("day", cellFactory.getPropertyValue(cellObject, "iso"));
        }
        return null;
    }
};

TableSheet.CellFactory.prototype.getLinkText = function (cellObject) {
    let href = cellObject.href;
    if (!href) {
        return null;
    }
    let content = cellObject.title;
    if (!content) {
        let index = href.indexOf("://");
        if (index > -1) {
            content = href.substring(index + 3);
        } else {
            content = href;
        }
    }
    let title = cellObject.comment;
    return Bdf.render("tablesheet:type/link", {
        href: href,
        content: content,
        title: title
    });
};

TableSheet.CellFactory.prototype.getNumberText = function (cellObject) {
    var text = this.getLabel(cellObject);
    if (!text) {
        text = this.getPropertyValue(cellObject, ["code", "value"]);
    }
    return text;
};

TableSheet.CellFactory.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;
};

TableSheet.CellFactory.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;
};

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