var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
import { EntityManager } from './../data/entity-manager';
import { ServiceBase } from "../data/service-base";
import * as breeze from 'breeze-client';
import { Container, observable, BindingEngine, computedFrom } from 'aurelia-framework';
export var ManyToManyRelationHelper = (function () {
    function ManyToManyRelationHelper() {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        var _this = this;
        this.previousSelectedEntitiesId = [];
        this.isCancelling = false;
        this.isInitializing = false;
        this.manager = Container.instance.get(EntityManager).manager;
        this.bindingEngine = Container.instance.get(BindingEngine);
        if (args.length == 7) {
            this.explicitConstructor(args);
        }
        else {
            this.autoConstructor(args);
        }
        var tagFieldName = this.service.displayNames[0];
        if (args.length === 4) {
            if (typeof args[2] === 'string') {
                tagFieldName = args[2];
            }
            else {
                this.createTagFn = args[2];
            }
        }
        this.createTagFn = this.createTagFn || function (value) {
            var _a;
            return this.service.createEntity((_a = {},
                _a[tagFieldName] = value,
                _a), true);
        };
        this.entityChangedKey = this.manager.entityChanged.subscribe(function (data) {
            if (data.entity.entityType.shortName == _this.linkEntityTypeName && (data.entityAction == breeze.EntityAction.RejectChanges || data.entityAction == breeze.EntityAction.Detach)) {
                _this.cancel();
            }
        });
        var self = this;
        this.initialize(self);
    }
    Object.defineProperty(ManyToManyRelationHelper.prototype, "service", {
        get: function () {
            if (this.innerService == null) {
                this.innerService = new ServiceBase(this.targetEntityTypeName);
            }
            return this.innerService;
        },
        enumerable: false,
        configurable: true
    });
    ManyToManyRelationHelper.prototype.autoConstructor = function (args) {
        var _this = this;
        this.entity = args[0];
        var fkPropertyName = args[1];
        var navProp = this.entity.entityType.navigationProperties.find(function (fkp) { return fkp.name == fkPropertyName; });
        this.linkEntitiesArray = this.entity[fkPropertyName];
        this.bindingEngine.collectionObserver(this.linkEntitiesArray).subscribe(function () {
            _this.cancel();
        });
        this.linkEntityTypeName = navProp.entityType.shortName;
        var inverseFkName = navProp.invForeignKeyNames[0];
        var fkPropTargets = navProp.entityType.foreignKeyProperties.filter(function (p) { return p.name != inverseFkName && p.name != 'createdById' && p.name != 'updatedById'; });
        var fkPropTarget;
        if (args[3] != null) {
            fkPropTarget = fkPropTargets.find(function (p) { return p.name == args[3]; });
        }
        else {
            fkPropTarget = fkPropTargets[0];
        }
        var fkPropTargetName = fkPropTarget.relatedNavigationProperty.name;
        var fkPropTargetIdName = fkPropTarget.name;
        this.targetEntityTypeName = fkPropTarget.relatedNavigationProperty.entityType.shortName;
        this.targetEntitySelector = function (e) { return e[fkPropTargetName]; };
        this.targetEntityIdSelector = function (e) { return e[fkPropTarget.name]; };
        this.createMapEntityKey = function (id) {
            var initialValues = {};
            initialValues[inverseFkName] = _this.entity.id;
            initialValues[fkPropTargetIdName] = id;
            return initialValues;
        };
    };
    ManyToManyRelationHelper.prototype.explicitConstructor = function (args) {
        this.entity = args[0];
        this.linkEntitiesArray = args[1];
        this.linkEntityTypeName = args[2];
        this.targetEntityTypeName = args[3];
        this.targetEntitySelector = args[4];
        this.targetEntityIdSelector = args[5];
        this.createMapEntityKey = args[6];
    };
    ManyToManyRelationHelper.prototype.unbind = function () {
        this.manager.entityChanged.unsubscribe(this.entityChangedKey);
        if (this.dataObserveSubscription)
            this.dataObserveSubscription.dispose();
    };
    ManyToManyRelationHelper.prototype.addLinkEntity = function (entity) {
        var self = this;
        if (entity) {
            var oldIds = self.selectedEntitiesId.concat();
            self.selectedEntities.push(entity);
            self.selectedEntitiesId.push(entity.id);
            var newIds = self.selectedEntitiesId.concat();
            this.selectedEntitiesIdChanged(newIds, oldIds);
        }
    };
    ManyToManyRelationHelper.prototype.cancel = function () {
        this.isCancelling = true;
        this.initializeData(this);
        this.isCancelling = false;
    };
    ManyToManyRelationHelper.prototype.reset = function () {
        this.initializeData(this);
    };
    ManyToManyRelationHelper.prototype.selectedEntitiesIdChanged = function (newValue, oldValue) {
        var _this = this;
        if (!this.isInitializing) {
            if (this.selectedEntitiesId == null)
                this.selectedEntitiesId = [];
            this.observeData();
            if (newValue.equals(this.previousSelectedEntitiesId) === false && !this.isCancelling) {
                if (this.entity.isEditable && this.entity.entityAspect.entityState != breeze.EntityState.Added) {
                    console.log("set entity as modified");
                    this.entity.entityAspect.setModified();
                }
            }
            var newTags_1 = newValue.reduce(function (newTags, val, index) {
                var searchEntity = _this.linkEntitiesArray.filter(function (emp) { return _this.targetEntityIdSelector(emp) == val; });
                if (searchEntity == null || searchEntity.length === 0) {
                    if (typeof val === 'string') {
                        newTags.push(val);
                        val = _this.createTagFn(val).id;
                    }
                    var initialValues = _this.createMapEntityKey(val);
                    console.log("create a linkedentity");
                    _this.service.createLinkedEntity(_this.linkEntityTypeName, initialValues);
                }
                return newTags;
            }, []);
            var entitiesToRemove = [];
            this.linkEntitiesArray.forEach(function (existingEntity) {
                if (newValue.filter(function (x) { return x == _this.targetEntityIdSelector(existingEntity) || newTags_1.find(function (newTag) { return newTag === x; }); }).length == 0) {
                    console.log("push an entity to remove", existingEntity);
                    entitiesToRemove.push(existingEntity);
                }
            });
            if (entitiesToRemove.length > 0) {
                entitiesToRemove.forEach(function (entityToRemove) {
                    if (entityToRemove.entityAspect.entityState === breeze.EntityState.Added) {
                        console.log("set entity to be detached");
                        entityToRemove.entityAspect.setDetached();
                    }
                    else {
                        console.log("set entity to be deleted");
                        entityToRemove.entityAspect.setDeleted();
                    }
                });
            }
            this.previousSelectedEntitiesId = [];
            newValue.forEach(function (id) { return _this.previousSelectedEntitiesId.push(id); });
        }
    };
    ManyToManyRelationHelper.prototype.initialize = function (self) {
        this.initializeData(this);
    };
    ManyToManyRelationHelper.prototype.initializeData = function (self) {
        var _a;
        this.isInitializing = true;
        if (this.selectedEntitiesId == null)
            this.selectedEntitiesId = [];
        if (this.targetEntitySelector != null)
            var entities = this.linkEntitiesArray.map(this.targetEntitySelector);
        this.selectedEntities = entities;
        if (entities != null && entities.length > 0 && entities[0] != null) {
            var entitiesId = entities.map(function (x) { return x.id; });
            entitiesId.forEach(function (id) { return self.previousSelectedEntitiesId.push(id); });
            this.selectedEntitiesId.splice(0);
            (_a = self.selectedEntitiesId).push.apply(_a, __spreadArray([], __read(entitiesId), false));
        }
        else {
            this.selectedEntitiesId.splice(0);
        }
        this.observeData();
        this.isInitializing = false;
    };
    ManyToManyRelationHelper.prototype.observeData = function () {
        var _this = this;
        if (this.dataObserveSubscription)
            this.dataObserveSubscription.dispose();
        this.dataObserveSubscription = this.bindingEngine
            .collectionObserver(this.selectedEntitiesId)
            .subscribe(function (splices) { return _this.dataChanged(splices); });
    };
    ManyToManyRelationHelper.prototype.dataChanged = function (splices) {
        if (splices.length > 0) {
            var newValue = this.selectedEntitiesId.slice(0);
            var oldValue = this.selectedEntitiesId.slice(0);
            if (splices[0].addedCount > 0) {
                oldValue.splice(splices[0].index, splices[0].addedCount);
            }
            if (splices[0].removed && splices[0].removed.length > 0) {
                splices[0].removed.forEach(function (r) { return oldValue.push(r); });
            }
            this.selectedEntitiesIdChanged(newValue, oldValue);
        }
    };
    __decorate([
        observable,
        __metadata("design:type", Array)
    ], ManyToManyRelationHelper.prototype, "selectedEntitiesId", void 0);
    __decorate([
        computedFrom("targetEntityTypeName"),
        __metadata("design:type", ServiceBase),
        __metadata("design:paramtypes", [])
    ], ManyToManyRelationHelper.prototype, "service", null);
    return ManyToManyRelationHelper;
}());

//# sourceMappingURL=relation-helper.js.map
