"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RowXform = void 0;
const base_xform_1 = require("../base-xform.js");
const cell_xform_1 = require("./cell-xform.js");
const utils_1 = require("../../../../../utils/utils.js");
const col_cache_1 = require("../../../utils/col-cache.js");
class RowXform extends base_xform_1.BaseXform {
    constructor(options) {
        super();
        this.maxItems = options && options.maxItems;
        this.map = {
            c: new cell_xform_1.CellXform()
        };
    }
    get tag() {
        return "row";
    }
    reset() {
        super.reset();
        this.numRowsSeen = 0;
        this.lastCellCol = 0;
    }
    prepare(model, options) {
        const styleId = options.styles.addStyleModel(model.style);
        if (styleId) {
            model.styleId = styleId;
        }
        const cellXform = this.map.c;
        model.cells.forEach((cellModel) => {
            cellXform.prepare(cellModel, options);
        });
    }
    render(xmlStream, model, options) {
        if (!model) {
            return;
        }
        xmlStream.openNode("row");
        xmlStream.addAttribute("r", model.number);
        if (model.height) {
            xmlStream.addAttribute("ht", model.height);
            xmlStream.addAttribute("customHeight", "1");
        }
        if (model.hidden) {
            xmlStream.addAttribute("hidden", "1");
        }
        if (model.min > 0 && model.max > 0 && model.min <= model.max) {
            xmlStream.addAttribute("spans", `${model.min}:${model.max}`);
        }
        if (model.styleId) {
            xmlStream.addAttribute("s", model.styleId);
            xmlStream.addAttribute("customFormat", "1");
        }
        // Output dyDescent if present (MS extension for font descent)
        if (model.dyDescent !== undefined) {
            xmlStream.addAttribute("x14ac:dyDescent", model.dyDescent);
        }
        if (model.outlineLevel) {
            xmlStream.addAttribute("outlineLevel", model.outlineLevel);
        }
        if (model.collapsed) {
            xmlStream.addAttribute("collapsed", "1");
        }
        const cellXform = this.map.c;
        model.cells.forEach((cellModel) => {
            cellXform.render(xmlStream, cellModel, options);
        });
        xmlStream.closeNode();
    }
    parseOpen(node) {
        if (this.parser) {
            this.parser.parseOpen(node);
            return true;
        }
        if (node.name === "row") {
            this.numRowsSeen += 1;
            // Reset lastCellCol for each new row
            this.lastCellCol = 0;
            const spans = node.attributes.spans
                ? node.attributes.spans.split(":").map((span) => parseInt(span, 10))
                : [undefined, undefined];
            // If r attribute is missing, use numRowsSeen as the row number
            const rowNumber = node.attributes.r ? parseInt(node.attributes.r, 10) : this.numRowsSeen;
            const model = (this.model = {
                number: rowNumber,
                min: spans[0],
                max: spans[1],
                cells: []
            });
            if (node.attributes.s) {
                model.styleId = parseInt(node.attributes.s, 10);
            }
            if ((0, utils_1.parseBoolean)(node.attributes.hidden)) {
                model.hidden = true;
            }
            if ((0, utils_1.parseBoolean)(node.attributes.bestFit)) {
                model.bestFit = true;
            }
            if (node.attributes.ht) {
                model.height = parseFloat(node.attributes.ht);
            }
            if (node.attributes.outlineLevel) {
                model.outlineLevel = parseInt(node.attributes.outlineLevel, 10);
            }
            if ((0, utils_1.parseBoolean)(node.attributes.collapsed)) {
                model.collapsed = true;
            }
            if (node.attributes["x14ac:dyDescent"] !== undefined) {
                model.dyDescent = parseFloat(node.attributes["x14ac:dyDescent"]);
            }
            return true;
        }
        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)) {
                const cellModel = this.parser.model;
                // If cell has address, extract column number from it
                // Otherwise, calculate address based on position
                if (cellModel.address) {
                    const decoded = col_cache_1.colCache.decodeAddress(cellModel.address);
                    this.lastCellCol = decoded.col;
                }
                else {
                    // No r attribute, calculate address from position
                    this.lastCellCol += 1;
                    cellModel.address = col_cache_1.colCache.encodeAddress(this.model.number, this.lastCellCol);
                }
                this.model.cells.push(cellModel);
                if (this.maxItems && this.model.cells.length > this.maxItems) {
                    throw new Error(`Max column count (${this.maxItems}) exceeded`);
                }
                this.parser = undefined;
            }
            return true;
        }
        return false;
    }
    reconcile(model, options) {
        model.style = model.styleId !== undefined ? options.styles.getStyleModel(model.styleId) : {};
        if (model.styleId !== undefined) {
            model.styleId = undefined;
        }
        const cellXform = this.map.c;
        model.cells.forEach((cellModel) => {
            cellXform.reconcile(cellModel, options);
        });
    }
}
exports.RowXform = RowXform;
