import * as React from "react";
export class ContentChildrenManager {
    constructor(getPropsKey, getKey, updateContentChildren) {
        this._contentChildren = null;
        this._contentChildrenActual = null;
        this._contentChildrenMap = null;
        this._contentChildrenUnresolved = 0;
        this.getChildRef = this.getChildRef.bind(this);
        this._getPropsKey = getPropsKey;
        this._getKey = getKey;
        this._updateContentChildren = updateContentChildren;
    }
    getChildren(propChildren) {
        let children = [];
        React.Children.forEach(propChildren, (ch) => {
            let key = this._getPropsKey(ch);
            if (key === undefined) {
                throw new Error("each child must have a unique key or name property");
            }
            children.push(React.cloneElement(ch, {
                key: key,
                ref: this.getChildRef
            }));
        });
        this._contentChildren = children;
        let prevActual = this._contentChildrenActual;
        this._contentChildrenActual = [];
        let prevMap = this._contentChildrenMap;
        this._contentChildrenMap = new Map();
        this._contentChildrenUnresolved = 0;
        if (this._contentChildren) {
            this._contentChildren.map((ch, i) => {
                let key = this._getPropsKey(ch);
                if (prevMap && prevMap.has(key)) {
                    this._contentChildrenActual[i] = prevActual[prevMap.get(key)];
                }
                else {
                    this._contentChildrenActual[i] = null;
                    this._contentChildrenUnresolved++;
                }
                this._contentChildrenMap.set(key, i);
            });
        }
        return children;
    }
    getChildRef(child) {
        //console.log(child);
        this.trackChild(child);
    }
    get contentChildrenActual() {
        return this._contentChildrenActual;
    }
    trackChild(child) {
        if (child === null) {
            return;
        }
        let name = this._getKey(child);
        let index = this._contentChildrenMap.get(name);
        if (this._contentChildrenActual[index] === null) {
            this._contentChildrenActual[index] = child;
            this._contentChildrenUnresolved--;
            if (this._contentChildrenUnresolved <= 0) {
                this._updateContentChildren();
            }
        }
    }
}
