(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./ExpressionParser"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.bindSymbol = void 0;
    const ExpressionParser_1 = require("./ExpressionParser");
    const isEvent = /^event/i;
    // function oneTime(name: string, b: Bind, control: IAtomComponent, e: any) {
    //     control.runAfterInit(() => {
    //         control.setLocalValue(e, name, b.sourcePath(control, e));
    //     });
    // }
    // function event(name: string, b: Bind, control: IAtomComponent, e: any) {
    //     control.runAfterInit(() => {
    //         if (isEvent.test(name)) {
    //             name = name.substr(5);
    //             name = (name[0].toLowerCase() + name.substr(1));
    //         }
    //         control.bindEvent(e, name, (e1) => {
    //             return (b.sourcePath as any)(control, e1);
    //         });
    //     });
    // }
    // function oneWay(name: string, b: Bind, control: IAtomComponent, e: any, creator: any) {
    //     if (b.pathList) {
    //         control.bind(e, name, b.pathList , false, () => {
    //             // tslint:disable-next-line: ban-types
    //             return (b.sourcePath as Function).call(creator, control, e);
    //         });
    //         return;
    //     }
    //     if (b.combined) {
    //         const a = {
    //             // it is `this`
    //             t: creator,
    //             // it is first parameter
    //             x: control
    //         };
    //         control.bind(e, name, b.combined , false, () => {
    //             // tslint:disable-next-line: ban-types
    //             return (b.sourcePath as Function).call(creator, control, e);
    //         }, a);
    //         return;
    //     }
    //     if (b.thisPathList) {
    //         control.bind(e, name, b.thisPathList , false, () => {
    //             // tslint:disable-next-line: ban-types
    //             return (b.sourcePath as Function).call(creator, control, e);
    //         }, creator);
    //         return;
    //     }
    // }
    // function twoWays(name: string, b: Bind, control: IAtomComponent, e: any, creator: any) {
    //     control.bind(e,
    //         name,
    //         b.thisPathList || b.pathList, (b.eventList as any) || true, null, b.thisPathList ? creator : undefined);
    // }
    function twoWaysConvert(name, b, control, e, creator) {
        control.bind(e, name, b.thisPathList || b.pathList, b.eventList || true, null, b.thisPathList ? creator : undefined);
    }
    exports.bindSymbol = Symbol("Bind");
    class Bind {
        constructor(setupFunction, sourcePath, name, eventList) {
            this.setupFunction = setupFunction;
            this.name = name;
            this.eventList = eventList;
            this.sourcePath = sourcePath;
            this[exports.bindSymbol] = true;
            if (!this.sourcePath) {
                return;
            }
            if (Array.isArray(this.sourcePath)) {
                this.pathList = this.sourcePath;
                // this.setupFunction = null;
            }
            else {
                const lists = ExpressionParser_1.parsePathLists(this.sourcePath);
                if (lists.combined.length) {
                    this.combined = lists.combined;
                }
                if (lists.pathList.length) {
                    this.pathList = lists.pathList;
                }
                if (lists.thisPath.length) {
                    this.thisPathList = lists.thisPath;
                }
                // if (setupFunction === oneWay) {
                //     if (!(this.combined || this.pathList || this.thisPathList)) {
                //         throw new Error(`Failed to setup binding for ${this.sourcePath}, parsing failed`);
                //     }
                // }
            }
        }
        static forControl() {
            return Bind;
        }
        static forData() {
            return Bind;
        }
        static forViewModel() {
            return Bind;
        }
        static forLocalViewModel() {
            return Bind;
        }
        static presenter(name) {
            return {
                [exports.bindSymbol](cn, control, e, creator) {
                    const n = name || cn;
                    let c = control.element;
                    while (c) {
                        if (c.atomControl && c.atomControl[n] !== undefined) {
                            break;
                        }
                        c = c._logicalParent || c.parentElement;
                    }
                    ((c && c.atomControl) || control)[n] = e;
                }
            };
        }
        // tslint:disable-next-line: ban-types
        static event(sourcePath) {
            return {
                [exports.bindSymbol](name, control, e) {
                    control.runAfterInit(() => {
                        if (isEvent.test(name)) {
                            name = name.substr(5);
                            name = (name[0].toLowerCase() + name.substr(1));
                        }
                        control.bindEvent(e, name, (e1) => {
                            return sourcePath(control, e1);
                        });
                    });
                }
            };
        }
        static oneTime(sourcePath) {
            return {
                [exports.bindSymbol](name, control, e) {
                    control.runAfterInit(() => {
                        control.setLocalValue(e, name, sourcePath(control, e));
                    });
                }
            };
        }
        static oneWay(sourcePath) {
            let pathList;
            let combined;
            let thisPathList;
            if (Array.isArray(sourcePath)) {
                pathList = sourcePath;
            }
            else {
                const lists = ExpressionParser_1.parsePathLists(sourcePath);
                if (lists.combined.length) {
                    combined = lists.combined;
                }
                if (lists.pathList.length) {
                    pathList = lists.pathList;
                }
                if (lists.thisPath.length) {
                    thisPathList = lists.thisPath;
                }
            }
            if (!(combined || pathList || thisPathList)) {
                throw new Error(`Failed to setup binding for ${sourcePath}, parsing failed`);
            }
            return {
                [exports.bindSymbol](name, control, e, creator) {
                    if (pathList) {
                        control.bind(e, name, pathList, false, () => {
                            return sourcePath.call(creator, control, e);
                        });
                        return;
                    }
                    if (combined) {
                        const a = {
                            t: creator,
                            x: control
                        };
                        control.bind(e, name, combined, false, () => {
                            return sourcePath.call(creator, control, e);
                        }, a);
                    }
                    if (thisPathList) {
                        control.bind(e, name, thisPathList, false, () => {
                            return sourcePath.call(creator, control, e);
                        }, creator);
                    }
                }
            };
        }
        static twoWays(sourcePath, events, converter) {
            let pathList;
            // let combined;
            let thisPathList;
            if (Array.isArray(sourcePath)) {
                pathList = sourcePath;
            }
            else {
                const lists = ExpressionParser_1.parsePathLists(sourcePath);
                if (lists.combined.length) {
                    // combined = lists.combined;
                    throw new Error("Cannot have combined binding for two ways");
                }
                if (lists.pathList.length) {
                    pathList = lists.pathList;
                }
                if (lists.thisPath.length) {
                    thisPathList = lists.thisPath;
                }
            }
            if (!(thisPathList || pathList)) {
                throw new Error(`Failed to setup twoWay binding on ${sourcePath}`);
            }
            return {
                [exports.bindSymbol](name, control, e, creator) {
                    control.bind(e, name, thisPathList || pathList, events || true, converter, thisPathList ? creator : undefined);
                }
            };
        }
        // public static twoWaysConvert<T extends IAtomComponent = IAtomComponent>(
        //     sourcePath: bindingFunction<T>): Bind {
        //     const b = new Bind(twoWays, sourcePath, null, events);
        //     if (!(b.thisPathList  || b.pathList)) {
        //         throw new Error(`Failed to setup twoWay binding on ${sourcePath}`);
        //     }
        //     return b;
        // }
        /**
         * Use this for HTML only, this will fire two way binding
         * as soon as the input/textarea box is updated
         * @param sourcePath binding lambda expression
         */
        static twoWaysImmediate(sourcePath) {
            return this.twoWays(sourcePath, ["change", "input", "paste"]);
            // const b = new Bind(twoWays, sourcePath, null,
            //     ["change", "input", "paste"]);
            // if (!(b.thisPathList  || b.pathList)) {
            //     throw new Error(`Failed to setup twoWay binding on ${sourcePath}`);
            // }
            // return b;
        }
    }
    exports.default = Bind;
});
//# sourceMappingURL=Bind.js.map