"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.NotationView = void 0;
const TSU = __importStar(require("@panyam/tsutils"));
const LineView_1 = require("./LineView");
const notation_1 = require("../notation");
const beatviews_1 = require("./beatviews");
class NotationView {
    constructor(rootElement, config) {
        this.rootElement = rootElement;
        this.config = config;
        this.lineViews = [];
        this.currentSVGElement = null;
        this.layoutChangeUnsubscribe = null;
        this.beatViews = new Map();
        this.markerViews = new Map();
        this.loadChildViews();
        if (config === null || config === void 0 ? void 0 : config.markdownParser) {
            this.markdownParser = config.markdownParser;
        }
    }
    get beatLayout() {
        return this._beatLayout;
    }
    set beatLayout(beatLayout) {
        this._beatLayout = beatLayout;
        beatLayout.gridLayoutGroup.getCellView = (cell) => this.viewForBeat(cell);
    }
    loadChildViews() {
        this.tableElement = TSU.DOM.createNode("table", {
            parent: this.rootElement,
            attrs: {
                class: "notationsContentRootTable",
            },
        });
    }
    renderNotation(notation, beatLayout) {
        this.notation = notation;
        this.beatLayout = beatLayout;
        const startTime = performance.now();
        this.refreshLayout();
        const layoutTime = performance.now();
        console.log(`V4 Document, Layout Time: ${layoutTime - startTime}ms`);
    }
    addNewRow(id, prefix, withAnnotation = true) {
        const tr = TSU.DOM.createNode("tr", {
            parent: this.tableElement,
            attrs: {
                class: prefix + "Row",
                id: prefix + "Row" + id,
            },
        });
        let td1 = null;
        if (withAnnotation) {
            td1 = TSU.DOM.createNode("td", {
                parent: tr,
                attrs: {
                    class: prefix + "AnnotationCell",
                    id: prefix + "Annotation" + id,
                },
            });
        }
        const td2 = TSU.DOM.createNode("td", {
            parent: tr,
            attrs: {
                class: prefix + "ContentCell",
                id: prefix + "Content" + id,
                colspan: withAnnotation ? 1 : 2,
            },
        });
        return [td1, td2];
    }
    newLineRoot(parent, line) {
        const [td1, td2] = this.addNewRow(line.uuid + "", "line");
        if (line.marginText) {
            td1.innerHTML = line.marginText;
        }
        return TSU.DOM.createSVGNode("svg", {
            parent: td2,
            attrs: {
                style: "margin-bottom: 10px",
                class: "lineRootSVG",
            },
        });
    }
    ensureLineView(line) {
        let lineView = this.getLineView(line);
        if (lineView == null) {
            const layoutParams = line.layoutParams || null;
            const svgElem = this.newLineRoot(this.tableElement, line);
            lineView = new LineView_1.LineView(svgElem, line, {
                layoutParams: layoutParams,
            });
            if (!line.isEmpty) {
                TSU.assert(layoutParams != null, "Layout params for a non empty line *should* exist");
                lineView.gridModel = this.beatLayout.getGridModelForLine(line.uuid);
            }
            this.lineViews.push(lineView);
        }
        return lineView;
    }
    getLineView(line) {
        return this.lineViews.find((l) => l.line == line) || null;
    }
    get currentLineView() {
        return this.lineViews[this.lineViews.length - 1];
    }
    clear() {
        this.lineViews = [];
        this.currentSVGElement = null;
        this.tableElement.innerHTML = "";
        this.beatViews = new Map();
    }
    refreshLayout() {
        const lineViews = [];
        this.processBlock(this.notation, lineViews);
        const now = performance.now();
        for (const lineView of lineViews) {
            lineView.gridModel.lastUpdatedAt = now;
        }
        this.beatLayout.gridLayoutGroup.refreshLayout();
        for (const lineView of lineViews) {
            lineView.wrapToSize();
        }
    }
    processBlock(block, lineViews) {
        for (const child of block.children()) {
            this.processBlockItem(child, lineViews);
        }
    }
    processBlockItem(item, lineViews) {
        if ((0, notation_1.isRawBlock)(item)) {
            this.renderBlock(item);
        }
        else if ((0, notation_1.isLine)(item)) {
            const line = item;
            if (!line.isEmpty) {
                const lineView = this.ensureLineView(line);
                lineViews.push(lineView);
            }
        }
        else if ((0, notation_1.isBlock)(item)) {
            this.processBlock(item, lineViews);
        }
    }
    renderBlock(raw) {
        const [, td2] = this.addNewRow(raw.uuid + "", "rawBlock", false);
        if (raw.contentType == "metadata") {
            const meta = this.notation.metadata.get(raw.content);
            if (meta) {
                if (meta.key.toLowerCase().indexOf(":") < 0) {
                    const div = td2.appendChild(TSU.DOM.createNode("div"));
                    const html = `<span class = "${meta.key.toLowerCase()}"><strong>${meta.key}</strong>: ${meta.value}</span>`;
                    div.innerHTML = html;
                }
            }
        }
        else {
            const div = td2.appendChild(TSU.DOM.createNode("div"));
            div.innerHTML = this.markdownParser(raw.content.trim());
        }
        this.currentSVGElement = null;
    }
    viewForBeat(cell) {
        if (cell.colIndex % 3 == 1) {
            const beat = cell.value;
            let curr = this.beatViews.get(beat.uuid) || null;
            if (curr == null) {
                const line = beat.role.line;
                const lineView = this.ensureLineView(line);
                const lp = line.layoutParams;
                curr = new beatviews_1.BeatView(cell, beat, lineView.gElem, lp.cycle);
                this.beatViews.set(beat.uuid, curr);
            }
            return curr;
        }
        else {
            const marker = cell.value;
            const beat = marker.beat;
            let curr = this.markerViews.get("pre:" + beat.uuid) || null;
            if (curr == null) {
                const line = beat.role.line;
                const lineView = this.ensureLineView(line);
                const lp = line.layoutParams;
                const isPreMarker = cell.colIndex % 3 == 0;
                curr = new beatviews_1.MarkerView(cell, beat, marker.markers, isPreMarker, lineView.gElem);
                this.markerViews.set("pre:" + beat.uuid, curr);
            }
            return curr;
        }
    }
}
exports.NotationView = NotationView;
//# sourceMappingURL=NotationView.js.map