"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.LeafAtomView = exports.GroupView = void 0;
exports.createAtomView = createAtomView;
const TSU = __importStar(require("@panyam/tsutils"));
const core_1 = require("../core");
const shapes_1 = require("../shapes");
const embelishments_1 = require("./embelishments");
const gamakas_1 = require("./gamakas");
class GroupView extends shapes_1.GroupView {
    createAtomView(atom) {
        return createAtomView(this.groupElement, atom, this.defaultToNotes, 0.7);
    }
}
exports.GroupView = GroupView;
class LeafAtomView extends shapes_1.LeafAtomView {
    constructor() {
        super(...arguments);
        this.leftSlot = [];
        this.topSlot = [];
        this.rightSlot = [];
        this.bottomSlot = [];
    }
    refreshBBox() {
        return TSU.DOM.svgBBox(this.rootGroup.element);
    }
    refreshMinSize() {
        const out = Object.assign({}, this.rootText.minSize);
        const totalWidth = this.leftSlot.reduce((a, b) => a + b.minSize.width, 0) +
            this.rightSlot.reduce((a, b) => a + b.minSize.width, 0) +
            this.leftSlot.length +
            this.rightSlot.length;
        const totalHeight = this.topSlot.reduce((a, b) => a + b.minSize.height, 0) +
            this.bottomSlot.reduce((a, b) => a + b.minSize.height, 0);
        out.width += totalWidth;
        out.height += totalHeight;
        return out;
    }
    get glyphOffset() {
        return (this.leftSlot.reduce((a, b) => a + b.minSize.width, 0) + this.leftSlot.length);
    }
    updateBounds(x, y, w, h) {
        return [x, y, NaN, NaN];
    }
    layoutElements() {
        const textSize = this.rootText.minSize;
        let currX = 0;
        let currY = this.hasY ? this.y : 0;
        for (const emb of this.leftSlot) {
            emb.x = currX;
            emb.refreshLayout();
            currX += emb.minSize.width + 1;
        }
        const textX = currX;
        this.rootText.x = currX;
        this.rootText.refreshLayout();
        currX += this.rootText.minSize.width;
        for (const emb of this.rightSlot) {
            emb.x = currX;
            emb.refreshLayout();
            currX += emb.minSize.width + 1;
        }
        const gminSize = this.glyph.minSize;
        const glyphX = textX + this.glyph.x;
        const glyphY = this.glyph.y;
        currY = glyphY - this.glyph.minSize.height + 5;
        for (const emb of this.topSlot) {
            const bb = emb.minSize;
            emb.setBounds(glyphX + (gminSize.width - bb.width) / 2, currY - bb.height, null, null, true);
            currY = emb.y;
        }
        currY = glyphY + 7;
        for (const emb of this.bottomSlot) {
            const bb = emb.minSize;
            emb.setBounds(glyphX + (gminSize.width - bb.width) / 2, currY, null, null, true);
            currY = emb.y + bb.height;
        }
        this.invalidateBounds();
    }
    refreshLayout() {
        this.layoutElements();
        this.rootGroup.element.setAttribute("transform", "translate(" + this.x + "," + this.y + ")");
    }
    addEmbelishment(slot, emb) {
        slot.push(emb);
    }
    orderEmbelishments() {
        const atom = this.leafAtom;
        if (atom.TYPE != core_1.AtomType.SYLLABLE && atom.TYPE != core_1.AtomType.NOTE) {
            return;
        }
        const lit = atom;
        if (lit.embelishments.length == 0)
            return;
        for (const emb of lit.embelishments) {
            switch (emb.type) {
                case gamakas_1.GamakaType.Kampitham:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Kampitham(this));
                    break;
                case gamakas_1.GamakaType.Nokku:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Nokku(this));
                    break;
                case gamakas_1.GamakaType.Spuritham:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Spuritham(this));
                    break;
                case gamakas_1.GamakaType.Prathyagatham:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Prathyagatham(this));
                    break;
                case gamakas_1.GamakaType.Orikkai:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Orikkai(this));
                    break;
                case gamakas_1.GamakaType.Odukkal:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Odukkal(this));
                    break;
                case gamakas_1.GamakaType.Aahaatam_Raavi:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Raavi(this));
                    break;
                case gamakas_1.GamakaType.Aahaatam_Kandippu:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Kandippu(this));
                    break;
                case gamakas_1.GamakaType.Vaali:
                    this.addEmbelishment(this.topSlot, new embelishments_1.Vaali(this));
                    break;
                case gamakas_1.GamakaType.Jaaru_Eetra:
                case gamakas_1.GamakaType.Jaaru_Irakka:
                    this.addEmbelishment(this.leftSlot, new embelishments_1.Jaaru(emb, this));
                    break;
            }
        }
    }
    embRoot() {
        return this.rootGroup.element;
    }
    needsRootElement() {
        return true;
    }
    createElements(parent) {
        this.createGlyphRoot(parent);
        this.createGlyphElement();
        this.orderEmbelishments();
        this.createPostSpacingElement();
        this.invalidateBounds();
    }
    createGlyphRoot(parent) {
        this.rootGroup = new shapes_1.ElementShape(TSU.DOM.createSVGNode("g", {
            doc: document,
            parent: parent,
            attrs: {
                atomid: this.leafAtom.uuid,
                class: "atomViewRootGroup",
                id: "atomViewRootGroup" + this.leafAtom.uuid,
            },
        }));
        this.rootText = new shapes_1.ElementShape(TSU.DOM.createSVGNode("text", {
            doc: document,
            parent: this.rootGroup.element,
            attrs: {
                atomid: this.leafAtom.uuid,
                class: "atomViewTextRoot",
                id: "atomViewTextRoot" + this.leafAtom.uuid,
            },
        }));
    }
    createGlyphElement() {
        const atom = this.leafAtom;
        this.glyph = new shapes_1.ElementShape(TSU.DOM.createSVGNode("tspan", {
            doc: document,
            parent: this.rootText.element,
            attrs: {
                atomid: atom.uuid,
                id: "atomGlyph" + atom.uuid,
            },
            text: this.glyphLabel,
        }));
    }
    createPostSpacingElement() {
        if (this.leafAtom.beforeRest) {
            this.postSpacingSpan = TSU.DOM.createSVGNode("tspan", {
                doc: document,
                parent: this.rootText.element,
                attrs: {
                    atomid: this.leafAtom.uuid,
                    id: "postSpacing" + this.leafAtom.uuid,
                },
                text: this.leafAtom.beforeRest ? " - " : "  ",
            });
        }
    }
}
exports.LeafAtomView = LeafAtomView;
class SpaceView extends LeafAtomView {
    get glyphLabel() {
        if (this.space.isSilent)
            return " ";
        if (this.space.duration.isOne)
            return ",";
        if (this.space.duration.cmpNum(2) == 0)
            return ";";
        return "_";
    }
    get space() {
        return this.leafAtom;
    }
}
class NoteView extends LeafAtomView {
    get glyphLabel() {
        return this.note.value;
    }
    needsRootElement() {
        return true;
    }
    createGlyphElement() {
        super.createGlyphElement();
        if (this.note.shift == true || this.note.shift != 0) {
            this.shiftElement = TSU.DOM.createSVGNode("tspan", {
                doc: document,
                parent: this.rootText.element,
                attrs: {
                    atomid: this.note.uuid,
                    class: "noteShiftTSpan",
                    id: "noteShift" + this.note.uuid,
                    "baseline-shift": "sub",
                },
                text: (this.note.shift == true ? "*" : this.note.shift) + " ",
            });
        }
    }
    moveGlyphToRoot() {
        if (this.shiftElement) {
            this.rootGroup.element.appendChild(this.shiftElement);
        }
    }
    orderEmbelishments() {
        const note = this.note;
        if (note.octave > 0) {
            this.topSlot.push(new embelishments_1.OctaveIndicator(this, note));
        }
        else if (this.note.octave < 0) {
            this.bottomSlot.push(new embelishments_1.OctaveIndicator(this, note));
        }
        super.orderEmbelishments();
    }
    get note() {
        return this.leafAtom;
    }
}
class SyllableView extends LeafAtomView {
    get glyphLabel() {
        return this.syllable.value;
    }
    get syllable() {
        return this.leafAtom;
    }
}
function createAtomView(parent, atom, litDefaultsToNote = false, groupViewScale = 1.0) {
    let out;
    switch (atom.TYPE) {
        case core_1.AtomType.SPACE:
            out = new SpaceView(atom);
            break;
        case core_1.AtomType.SYLLABLE:
            out = new SyllableView(atom);
            break;
        case core_1.AtomType.NOTE:
            out = new NoteView(atom);
            break;
        case core_1.AtomType.LITERAL:
            if (litDefaultsToNote) {
                const lit = core_1.Note.fromLit(atom);
                out = new NoteView(lit);
            }
            else {
                const lit = core_1.Syllable.fromLit(atom);
                out = new SyllableView(lit);
            }
            break;
        case core_1.AtomType.GROUP:
            out = new GroupView(atom);
            out.defaultToNotes = litDefaultsToNote;
            out.scaleFactor = groupViewScale;
            break;
        default:
            throw new Error("Invalid atom type: " + atom.TYPE);
    }
    out.createElements(parent);
    return out;
}
//# sourceMappingURL=atomviews.js.map