"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stopPropagation = exports.cancelAnimation = exports.animate = exports.removeParentChild = exports.appendParentChild = exports.registerRoot = exports.unregisterRoot = exports.reorderParentRoot = exports.reorderRoot = exports.unregisterParentRoot = exports.registerParentRoot = exports.refSlot = exports.refChildren = exports.refChild = exports.removeChild = exports.pullChild = exports.hasChild = exports.insertChild = exports.pushChild = exports.instanceChild = exports.appendChild = void 0;
const ChildOutOfBoundError_1 = require("../exception/ChildOutOfBoundError");
const evaluate_1 = require("../spec/evaluate");
const array_1 = require("../util/array");
function appendChild(component, children, Class) {
    const i = pushChild(component, children, Class);
    const { __bundle: bundle } = Class;
    component.emit('append_child', bundle, []);
    return i;
}
exports.appendChild = appendChild;
function instanceChild(component, Class) {
    const system = component.refSystem();
    const unit = new Class(system);
    const { input = {}, output = {}, memory = { input: {}, output: {}, memory: {} }, } = Class.__bundle.unit;
    for (const name in input) {
        const { data } = input[name];
        if (data !== undefined) {
            const _data = (0, evaluate_1.evaluate)(data, system.specs, system.classes);
            unit.pushInput(name, _data);
        }
    }
    // unit.restore(memory)
    if (component.paused() && !unit.paused()) {
        unit.pause();
    }
    else if (!component.paused() && unit.paused()) {
        unit.play();
    }
    return unit;
}
exports.instanceChild = instanceChild;
function pushChild(component, children, Class) {
    const unit = instanceChild(component, Class);
    children.push(unit);
    const i = children.length - 1;
    return i;
}
exports.pushChild = pushChild;
function insertChild(component, children, Class, at) {
    const unit = instanceChild(component, Class);
    (0, array_1.insert)(children, unit, at);
    const { __bundle: bundle } = Class;
    component.emit('insert_child', bundle, at, []);
}
exports.insertChild = insertChild;
function hasChild(element, children, at) {
    const has = at >= 0 && at < children.length;
    return has;
}
exports.hasChild = hasChild;
function pullChild(element, children, at) {
    const has = hasChild(element, children, at);
    if (!has) {
        throw new ChildOutOfBoundError_1.ChildOutOfBound();
    }
    const [unit] = children.splice(at, 1);
    return unit;
}
exports.pullChild = pullChild;
function removeChild(element, children, at) {
    const child = pullChild(element, children, at);
    element.emit('remove_child', at, []);
    element.emit(`remove_child_at_${at}`, at);
    return child;
}
exports.removeChild = removeChild;
function refChild(element, children, at) {
    return children[at];
}
exports.refChild = refChild;
function refChildren(element, children) {
    return children;
}
exports.refChildren = refChildren;
function refSlot(element, slotName, slot) {
    return slot[slotName] || element;
}
exports.refSlot = refSlot;
function registerParentRoot(component, parentRoot, child, slotName, at) {
    if (at === undefined) {
        parentRoot.push(child);
    }
    else {
        (0, array_1.insert)(parentRoot, child, at);
    }
    component.emit('register_parent_root', child, slotName);
    const slot = component.refSlot(slotName);
    slot.appendParentChild(component, 'default');
}
exports.registerParentRoot = registerParentRoot;
function unregisterParentRoot(component, parentRoot, child) {
    const at = parentRoot.indexOf(child);
    parentRoot.splice(at, 1);
    component.emit('unregister_parent_root', component);
}
exports.unregisterParentRoot = unregisterParentRoot;
function reorderRoot(component, root, child, to) {
    const currentIndex = root.indexOf(child);
    if (currentIndex === -1) {
        throw new Error('root not found');
    }
    root.splice(currentIndex, 1);
    (0, array_1.insert)(root, child, to);
    component.emit('reorder_root', component, to);
}
exports.reorderRoot = reorderRoot;
function reorderParentRoot(component, parentRoot, child, to) {
    const currentIndex = parentRoot.indexOf(child);
    if (currentIndex === -1) {
        throw new Error('root not found');
    }
    parentRoot.splice(currentIndex, 1);
    (0, array_1.insert)(parentRoot, child, to);
    component.emit('reorder_parent_root', component, to);
}
exports.reorderParentRoot = reorderParentRoot;
function unregisterRoot(component, root, child) {
    const at = root.indexOf(child);
    root.splice(at, 1);
    component.emit('unregister_root', component);
}
exports.unregisterRoot = unregisterRoot;
function registerRoot(component, root, child) {
    root.push(child);
    component.emit('register_root', component);
}
exports.registerRoot = registerRoot;
function appendParentChild(component, parentChild, child, slotName) {
    const slot = component.refSlot(slotName);
    if (component === slot) {
        parentChild.push(child);
        component.emit('append_parent_child', component, slotName);
    }
    else {
        slot.appendParentChild(child, 'default');
    }
}
exports.appendParentChild = appendParentChild;
function removeParentChild(component, parentRoot, child) {
    const at = parentRoot.indexOf(child);
    parentRoot.splice(at, 1);
    component.emit('remove_parent_child', component);
}
exports.removeParentChild = removeParentChild;
function animate(component, animations, keyframes, opt) {
    animations.push({ keyframes, opt });
    component.emit('call', {
        method: 'animate',
        data: [keyframes, opt],
    });
}
exports.animate = animate;
function cancelAnimation(component, animations, id) {
    const i = animations.findIndex((animation) => {
        return animation.opt.id === id;
    });
    animations.splice(i, 1);
    component.emit('call', {
        method: 'cancelAnimation',
        data: [id],
    });
}
exports.cancelAnimation = cancelAnimation;
function stopPropagation(component, stopPropagationCount, name) {
    var _a;
    stopPropagationCount[name] = (_a = stopPropagationCount[name]) !== null && _a !== void 0 ? _a : 0;
    stopPropagationCount[name]++;
    component.emit('call', { method: 'stopPropagation', data: [name] });
    return () => {
        stopPropagationCount[name]--;
        if (stopPropagationCount[name] === 0) {
            delete stopPropagationCount[name];
            component.emit('call', { method: 'cancelStopPropagation', data: [name] });
        }
    };
}
exports.stopPropagation = stopPropagation;
//# sourceMappingURL=method.js.map