(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 });
    var ExpressionParser_1 = require("./ExpressionParser");
    var isEvent = /^event/i;
    function oneTime(name, b, control, e) {
        control.runAfterInit(function () {
            control.setLocalValue(e, name, b.sourcePath(control, e));
        });
    }
    function event(name, b, control, e) {
        control.runAfterInit(function () {
            if (isEvent.test(name)) {
                name = name.substr(5);
                name = (name[0].toLowerCase() + name.substr(1));
            }
            control.bindEvent(e, name, function (e1) {
                return b.sourcePath(control, e1);
            });
        });
    }
    function oneWay(name, b, control, e, creator) {
        if (b.pathList) {
            control.bind(e, name, b.pathList, false, function () {
                // tslint:disable-next-line: ban-types
                return b.sourcePath.call(creator, control, e);
            });
            return;
        }
        if (b.combined) {
            var a = {
                // it is `this`
                t: creator,
                // it is first parameter
                x: control
            };
            control.bind(e, name, b.combined, false, function () {
                // tslint:disable-next-line: ban-types
                return b.sourcePath.call(creator, control, e);
            }, a);
            return;
        }
        if (b.thisPathList) {
            control.bind(e, name, b.thisPathList, false, function () {
                // tslint:disable-next-line: ban-types
                return b.sourcePath.call(creator, control, e);
            }, creator);
            return;
        }
    }
    function twoWays(name, b, control, e, creator) {
        control.bind(e, name, b.thisPathList || b.pathList, b.eventList || true, null, b.thisPathList ? creator : undefined);
    }
    function presenter(name, b, control, e) {
        var n = b.name || name;
        var c = control.element;
        while (c) {
            if (c.atomControl && c.atomControl[n] !== undefined) {
                break;
            }
            c = c._logicalParent || c.parentElement;
        }
        ((c && c.atomControl) || control)[n] = e;
    }
    var Bind = /** @class */ (function () {
        function Bind(setupFunction, sourcePath, name, eventList) {
            this.setupFunction = setupFunction;
            this.name = name;
            this.eventList = eventList;
            this.sourcePath = sourcePath;
            if (!this.sourcePath) {
                return;
            }
            if (Array.isArray(this.sourcePath)) {
                this.pathList = this.sourcePath;
                // this.setupFunction = null;
            }
            else {
                var 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;
                }
            }
        }
        Bind.forControl = function () {
            return Bind;
        };
        Bind.forData = function () {
            return Bind;
        };
        Bind.forViewModel = function () {
            return Bind;
        };
        Bind.forLocalViewModel = function () {
            return Bind;
        };
        Bind.presenter = function (name) {
            return new Bind(presenter, null, name);
        };
        // tslint:disable-next-line: ban-types
        Bind.event = function (sourcePath) {
            return new Bind(event, sourcePath);
        };
        Bind.oneTime = function (sourcePath) {
            return new Bind(oneTime, sourcePath);
        };
        Bind.oneWay = function (sourcePath) {
            return new Bind(oneWay, sourcePath);
        };
        Bind.twoWays = function (sourcePath, events) {
            var b = new Bind(twoWays, sourcePath, null, events);
            if (!(b.thisPathList || b.pathList)) {
                throw new Error("Failed to setup twoWay binding on " + sourcePath);
            }
            return b;
        };
        return Bind;
    }());
    exports.default = Bind;
});
//# sourceMappingURL=Bind.js.map