import { BaseXform } from "../base-xform.js";
import { CacheField } from "./cache-field.js";
import { CacheFieldXform } from "./cache-field-xform.js";
import { XmlStream } from "../../../utils/xml-stream.js";
class PivotCacheDefinitionXform extends BaseXform {
    constructor() {
        super();
        this.map = {};
        this.model = null;
        this.currentCacheField = null;
        this.inCacheFields = false;
        this.inCacheSource = false;
    }
    prepare(_model) {
        // No preparation needed for writing
    }
    get tag() {
        // http://www.datypic.com/sc/ooxml/e-ssml_pivotCacheDefinition.html
        return "pivotCacheDefinition";
    }
    reset() {
        this.model = null;
        this.currentCacheField = null;
        this.inCacheFields = false;
        this.inCacheSource = false;
    }
    /**
     * Render pivot cache definition XML.
     * Supports both newly created models (with PivotTableSource) and loaded models.
     */
    render(xmlStream, model) {
        // Check if this is a loaded model (has isLoaded flag or no source property)
        const isLoaded = model.isLoaded || !("source" in model);
        if (isLoaded) {
            this.renderLoaded(xmlStream, model);
        }
        else {
            this.renderNew(xmlStream, model);
        }
    }
    /**
     * Render newly created pivot cache definition
     */
    renderNew(xmlStream, model) {
        const { source, cacheFields } = model;
        // Record count = number of data rows (excluding header row)
        const recordCount = source.getSheetValues().slice(2).length;
        xmlStream.openXml(XmlStream.StdDocAttributes);
        xmlStream.openNode(this.tag, {
            ...PivotCacheDefinitionXform.PIVOT_CACHE_DEFINITION_ATTRIBUTES,
            "r:id": "rId1",
            refreshOnLoad: "1", // important for our implementation to work
            createdVersion: "8",
            refreshedVersion: "8",
            minRefreshableVersion: "3",
            recordCount
        });
        xmlStream.openNode("cacheSource", { type: "worksheet" });
        xmlStream.leafNode("worksheetSource", {
            ref: source.dimensions.shortRange,
            sheet: source.name
        });
        xmlStream.closeNode();
        xmlStream.openNode("cacheFields", { count: cacheFields.length });
        // Note: keeping this pretty-printed for now to ease debugging.
        xmlStream.writeXml(cacheFields.map((cacheField) => new CacheField(cacheField).render()).join("\n    "));
        xmlStream.closeNode();
        xmlStream.closeNode();
    }
    /**
     * Render loaded pivot cache definition (preserving original structure)
     */
    renderLoaded(xmlStream, model) {
        const { cacheFields, sourceRef, sourceSheet, sourceTableName, recordCount } = model;
        xmlStream.openXml(XmlStream.StdDocAttributes);
        xmlStream.openNode(this.tag, {
            ...PivotCacheDefinitionXform.PIVOT_CACHE_DEFINITION_ATTRIBUTES,
            "r:id": model.rId || "rId1",
            refreshOnLoad: model.refreshOnLoad || "1",
            createdVersion: model.createdVersion || "8",
            refreshedVersion: model.refreshedVersion || "8",
            minRefreshableVersion: model.minRefreshableVersion || "3",
            recordCount: recordCount || cacheFields.length + 1
        });
        xmlStream.openNode("cacheSource", { type: "worksheet" });
        // worksheetSource supports two reference styles:
        // 1. name: references a named Table
        // 2. ref + sheet: references a cell range on a worksheet
        const worksheetSourceAttrs = sourceTableName
            ? { name: sourceTableName }
            : { ref: sourceRef, sheet: sourceSheet };
        xmlStream.leafNode("worksheetSource", worksheetSourceAttrs);
        xmlStream.closeNode();
        xmlStream.openNode("cacheFields", { count: cacheFields.length });
        xmlStream.writeXml(cacheFields
            .map((cacheField) => new CacheField(cacheField).render())
            .join("\n    "));
        xmlStream.closeNode();
        xmlStream.closeNode();
    }
    parseOpen(node) {
        const { name, attributes } = node;
        // Delegate to current cacheField parser if active
        if (this.currentCacheField) {
            this.currentCacheField.parseOpen(node);
            return true;
        }
        switch (name) {
            case this.tag:
                // pivotCacheDefinition root element
                this.reset();
                this.model = {
                    cacheFields: [],
                    rId: attributes["r:id"],
                    refreshOnLoad: attributes.refreshOnLoad,
                    createdVersion: attributes.createdVersion,
                    refreshedVersion: attributes.refreshedVersion,
                    minRefreshableVersion: attributes.minRefreshableVersion,
                    recordCount: attributes.recordCount ? parseInt(attributes.recordCount, 10) : undefined,
                    isLoaded: true
                };
                break;
            case "cacheSource":
                this.inCacheSource = true;
                break;
            case "worksheetSource":
                if (this.inCacheSource && this.model) {
                    this.model.sourceRef = attributes.ref;
                    this.model.sourceSheet = attributes.sheet;
                    this.model.sourceTableName = attributes.name;
                }
                break;
            case "cacheFields":
                this.inCacheFields = true;
                break;
            case "cacheField":
                if (this.inCacheFields) {
                    this.currentCacheField = new CacheFieldXform();
                    this.currentCacheField.parseOpen(node);
                }
                break;
        }
        return true;
    }
    parseText(text) {
        if (this.currentCacheField) {
            this.currentCacheField.parseText(text);
        }
    }
    parseClose(name) {
        // Delegate to current cacheField parser if active
        if (this.currentCacheField) {
            if (!this.currentCacheField.parseClose(name)) {
                // cacheField parsing complete, add to model
                if (this.model && this.currentCacheField.model) {
                    this.model.cacheFields.push(this.currentCacheField.model);
                }
                this.currentCacheField = null;
            }
            return true;
        }
        switch (name) {
            case this.tag:
                // End of pivotCacheDefinition
                return false;
            case "cacheSource":
                this.inCacheSource = false;
                break;
            case "cacheFields":
                this.inCacheFields = false;
                break;
        }
        return true;
    }
    reconcile(_model, _options) {
        // No reconciliation needed
    }
}
PivotCacheDefinitionXform.PIVOT_CACHE_DEFINITION_ATTRIBUTES = {
    xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
    "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
};
export { PivotCacheDefinitionXform };
