import { XmlStream } from "../../../utils/xml-stream.js";
import { xmlEncode, xmlDecode } from "../../../../../utils/utils.js";
import { BaseXform } from "../base-xform.js";
class PivotCacheRecordsXform extends BaseXform {
    constructor() {
        super();
        this.map = {};
        this.model = null;
        this.currentRecord = null;
    }
    prepare(_model) {
        // No preparation needed
    }
    get tag() {
        // http://www.datypic.com/sc/ooxml/e-ssml_pivotCacheRecords.html
        return "pivotCacheRecords";
    }
    reset() {
        this.model = null;
        this.currentRecord = null;
    }
    /**
     * Render pivot cache records XML.
     * Supports both newly created models (with PivotTableSource) and loaded models.
     */
    render(xmlStream, model) {
        // Check if this is a loaded model
        const isLoaded = model.isLoaded || !("source" in model);
        if (isLoaded) {
            this.renderLoaded(xmlStream, model);
        }
        else {
            this.renderNew(xmlStream, model);
        }
    }
    /**
     * Render newly created pivot cache records
     */
    renderNew(xmlStream, model) {
        const { source, cacheFields } = model;
        const sourceBodyRows = source.getSheetValues().slice(2);
        xmlStream.openXml(XmlStream.StdDocAttributes);
        xmlStream.openNode(this.tag, {
            ...PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES,
            count: sourceBodyRows.length
        });
        xmlStream.writeXml(this.renderTableNew(sourceBodyRows, cacheFields));
        xmlStream.closeNode();
    }
    /**
     * Render loaded pivot cache records
     */
    renderLoaded(xmlStream, model) {
        xmlStream.openXml(XmlStream.StdDocAttributes);
        xmlStream.openNode(this.tag, {
            ...PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES,
            count: model.count
        });
        // Render each record
        for (const record of model.records) {
            xmlStream.writeXml("\n  <r>");
            for (const value of record) {
                xmlStream.writeXml("\n    ");
                xmlStream.writeXml(this.renderRecordValue(value));
            }
            xmlStream.writeXml("\n  </r>");
        }
        xmlStream.closeNode();
    }
    /**
     * Render a single record value to XML
     */
    renderRecordValue(value) {
        switch (value.type) {
            case "x":
                return `<x v="${value.value}" />`;
            case "n":
                return `<n v="${value.value}" />`;
            case "s":
                return `<s v="${xmlEncode(String(value.value))}" />`;
            case "b":
                return `<b v="${value.value ? "1" : "0"}" />`;
            case "m":
                return "<m />";
            case "d":
                return `<d v="${value.value.toISOString()}" />`;
            case "e":
                return `<e v="${value.value}" />`;
            default:
                return "<m />";
        }
    }
    // Helper methods for rendering new records
    renderTableNew(sourceBodyRows, cacheFields) {
        const parts = [];
        for (const row of sourceBodyRows) {
            const realRow = row.slice(1);
            parts.push("\n  <r>");
            for (let i = 0; i < realRow.length; i++) {
                parts.push("\n    ");
                parts.push(this.renderCellNew(realRow[i], cacheFields[i].sharedItems));
            }
            parts.push("\n  </r>");
        }
        return parts.join("");
    }
    renderCellNew(value, sharedItems) {
        // Handle null/undefined values first
        if (value === null || value === undefined) {
            return "<m />";
        }
        // no shared items
        if (sharedItems === null) {
            if (Number.isFinite(value)) {
                return `<n v="${value}" />`;
            }
            return `<s v="${xmlEncode(String(value))}" />`;
        }
        // shared items - use indexOf for value lookup (works for both string and numeric)
        const sharedItemsIndex = sharedItems.indexOf(value);
        if (sharedItemsIndex < 0) {
            throw new Error(`${JSON.stringify(value)} not in sharedItems ${JSON.stringify(sharedItems)}`);
        }
        return `<x v="${sharedItemsIndex}" />`;
    }
    parseOpen(node) {
        const { name, attributes } = node;
        switch (name) {
            case this.tag:
                // pivotCacheRecords root element
                this.reset();
                this.model = {
                    records: [],
                    count: parseInt(attributes.count || "0", 10),
                    isLoaded: true
                };
                break;
            case "r":
                // Start of a new record
                this.currentRecord = [];
                break;
            case "x":
                // Shared item index
                if (this.currentRecord) {
                    this.currentRecord.push({
                        type: "x",
                        value: parseInt(attributes.v || "0", 10)
                    });
                }
                break;
            case "n":
                // Numeric value
                if (this.currentRecord) {
                    this.currentRecord.push({
                        type: "n",
                        value: parseFloat(attributes.v || "0")
                    });
                }
                break;
            case "s":
                // String value
                if (this.currentRecord) {
                    this.currentRecord.push({
                        type: "s",
                        value: xmlDecode(attributes.v || "")
                    });
                }
                break;
            case "b":
                // Boolean value
                if (this.currentRecord) {
                    this.currentRecord.push({
                        type: "b",
                        value: attributes.v === "1"
                    });
                }
                break;
            case "m":
                // Missing/null value
                if (this.currentRecord) {
                    this.currentRecord.push({ type: "m" });
                }
                break;
            case "d":
                // Date value
                if (this.currentRecord) {
                    this.currentRecord.push({
                        type: "d",
                        value: new Date(attributes.v || "")
                    });
                }
                break;
            case "e":
                // Error value
                if (this.currentRecord) {
                    this.currentRecord.push({
                        type: "e",
                        value: attributes.v || ""
                    });
                }
                break;
        }
        return true;
    }
    parseText(_text) {
        // No text content in cache records elements
    }
    parseClose(name) {
        switch (name) {
            case this.tag:
                // End of pivotCacheRecords
                return false;
            case "r":
                // End of record - add to model
                if (this.model && this.currentRecord) {
                    this.model.records.push(this.currentRecord);
                    this.currentRecord = null;
                }
                break;
        }
        return true;
    }
    reconcile(_model, _options) {
        // No reconciliation needed
    }
}
PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES = {
    xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
    "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
    "xmlns:mc": "http://schemas.openxmlformats.org/markup-compatibility/2006",
    "mc:Ignorable": "xr",
    "xmlns:xr": "http://schemas.microsoft.com/office/spreadsheetml/2014/revision"
};
export { PivotCacheRecordsXform };
