"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.GroupView = exports.LeafAtomView = exports.AtomView = exports.ElementShape = exports.Embelishment = exports.Shape = void 0;
const TSU = __importStar(require("@panyam/tsutils"));
const core_1 = require("./core");
class Shape {
    constructor() {
        this.shapeId = Shape.idCounter++;
        this._x = null;
        this._y = null;
        this._width = null;
        this._height = null;
        this.parentShape = null;
        this.children = [];
    }
    get bbox() {
        if (!this._bbox) {
            this._bbox = this.refreshBBox();
        }
        return this._bbox;
    }
    get minSize() {
        if (!this._minSize) {
            this._minSize = this.refreshMinSize();
        }
        return this._minSize;
    }
    invalidateBounds() {
        this._minSize = null;
        this._bbox = null;
    }
    setBounds(x, y, w, h, applyLayout = false) {
        if (x != null) {
            if (isNaN(x)) {
                this._x = null;
            }
            else {
                this._x = x;
            }
        }
        if (y != null) {
            if (isNaN(y)) {
                this._y = null;
            }
            else {
                this._y = y;
            }
        }
        if (w != null) {
            if (isNaN(w)) {
                this._width = null;
            }
            else {
                this._width = w;
            }
        }
        if (h != null) {
            if (isNaN(h)) {
                this._height = null;
            }
            else {
                this._height = h;
            }
        }
        const [nx, ny, nw, nh] = this.updateBounds(x, y, w, h);
        if (nx != null) {
            if (isNaN(nx)) {
                this._x = null;
            }
            else {
                this._x = nx;
            }
        }
        if (ny != null) {
            if (isNaN(ny)) {
                this._y = null;
            }
            else {
                this._y = ny;
            }
        }
        if (nw != null) {
            if (isNaN(nw)) {
                this._width = null;
            }
            else {
                this._width = nw;
            }
        }
        if (nh != null) {
            if (isNaN(nh)) {
                this._height = null;
            }
            else {
                this._height = nh;
            }
        }
        if (applyLayout)
            this.refreshLayout();
        return [nx, ny, nw, nh];
    }
    get hasX() {
        return this._x != null && !isNaN(this._x);
    }
    get hasY() {
        return this._y != null && !isNaN(this._y);
    }
    get hasWidth() {
        return this._width != null && !isNaN(this._width);
    }
    get hasHeight() {
        return this._height != null && !isNaN(this._height);
    }
    get x() {
        return this._x || 0;
    }
    set x(x) {
        this.setBounds(x == null ? NaN : x, null, null, null);
    }
    get y() {
        if (this._y != null)
            return this._y;
        return 0;
    }
    set y(y) {
        this.setBounds(null, y == null ? NaN : y, null, null);
    }
    get width() {
        if (this._width != null)
            return this._width;
        return 0;
    }
    set width(w) {
        this.setBounds(null, null, w == null ? NaN : w, null);
    }
    get height() {
        if (this._height != null)
            return this._height;
        return 0;
    }
    set height(h) {
        this.setBounds(null, null, null, h == null ? NaN : h);
    }
    refreshLayout() {
    }
}
exports.Shape = Shape;
Shape.idCounter = 0;
class Embelishment extends Shape {
}
exports.Embelishment = Embelishment;
class ElementShape extends Shape {
    constructor(element) {
        super();
        this.element = element;
    }
    refreshBBox() {
        return TSU.DOM.svgBBox(this.element);
    }
    refreshMinSize() {
        return TSU.DOM.svgBBox(this.element);
    }
    updateBounds(x, y, w, h) {
        return [x, y, w, h];
    }
    refreshLayout() {
        if (this.hasX)
            this.element.setAttribute("x", "" + this._x);
        if (this.hasY)
            this.element.setAttribute("y", "" + this._y);
    }
}
exports.ElementShape = ElementShape;
class AtomView extends Shape {
    constructor() {
        super(...arguments);
        this.depth = 0;
        this.roleIndex = 0;
    }
}
exports.AtomView = AtomView;
class LeafAtomView extends AtomView {
    constructor(leafAtom) {
        super();
        this.leafAtom = leafAtom;
    }
    isLeaf() {
        return true;
    }
    get viewId() {
        return this.leafAtom.uuid;
    }
    get totalDuration() {
        return this.leafAtom.duration;
    }
}
exports.LeafAtomView = LeafAtomView;
class GroupView extends AtomView {
    constructor(group, config) {
        super();
        this.group = group;
        this.atomViews = [];
        this.defaultToNotes = true;
        this.needsLayout = true;
        this.scaleFactor = 1.0;
        this.atomSpacing = 5;
        this.setStyles(config || {});
    }
    get totalDuration() {
        return this.group.totalChildDuration;
    }
    createElements(parent) {
        this.groupElement = TSU.DOM.createSVGNode("g", {
            parent: parent,
            attrs: {
                class: "groupViewRoot",
                id: "groupViewRoot" + this.group.uuid,
            },
        });
        for (const atom of this.group.atoms.values()) {
            const atomView = this.createAtomView(atom);
            this.atomViews.push(atomView);
        }
        this.invalidateBounds();
    }
    isLeaf() {
        return false;
    }
    refreshBBox() {
        return TSU.DOM.svgBBox(this.groupElement);
    }
    refreshMinSize() {
        let totalWidth = 0;
        let maxHeight = 0;
        this.atomViews.forEach((av, index) => {
            const ms = av.minSize;
            totalWidth += ms.width + this.atomSpacing;
            maxHeight = Math.max(maxHeight, ms.height);
        });
        return new TSU.Geom.Size(totalWidth * this.scaleFactor, maxHeight * this.scaleFactor);
    }
    updateBounds(x, y, w, h) {
        return [x, y, w, h];
    }
    refreshLayout() {
        let transform = "translate(" + this.x + "," + this.y + ")";
        if (this.scaleFactor < 1) {
            transform += " scale(" + this.scaleFactor + ")";
        }
        this.groupElement.setAttribute("transform", transform);
        let currX = 0;
        const currY = 0;
        if (true) {
            this.atomViews.forEach((av, index) => {
                av.setBounds(currX, currY, null, null, true);
                currX += this.atomSpacing + av.minSize.width;
            });
        }
        else {
            const totalDur = this.group.totalChildDuration;
            let currTime = core_1.ZERO;
            this.atomViews.forEach((av, index) => {
                const newX = currTime.timesNum(this.minSize.width).divby(this.group.duration).floor;
                if (newX >= currX) {
                    currX = newX;
                }
                av.setBounds(currX, currY, null, null, true);
                currX += this.atomSpacing + av.minSize.width;
                currTime = currTime.plus(av.totalDuration);
            });
        }
        this.invalidateBounds();
        for (const e of this.embelishments)
            e.refreshLayout();
        this.invalidateBounds();
    }
    get embelishments() {
        if (!this._embelishments) {
            this._embelishments = this.createEmbelishments();
        }
        return this._embelishments;
    }
    createEmbelishments() {
        return [];
    }
    setStyles(config) {
        if ("atomSpacing" in config)
            this.atomSpacing = config.atomSpacing;
        this.needsLayout = true;
    }
}
exports.GroupView = GroupView;
//# sourceMappingURL=shapes.js.map