"use strict";
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);
};
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
const mobx_1 = require("mobx");
let doLog = false;
function log(message) {
    if (doLog) {
        console.log(message);
    }
}
const keyPrefix = "_PI_";
const listPartHandler = {
    set: function (target, num, value) {
        log("SET: " + target + " num: " + num + " value: " + value + " PA? " + (target instanceof PartArray));
        const index = Number(num);
        if (typeof num === "string") {
            if (isNaN(index)) {
                target[num] = value;
                log("Do nothing because typeof is " + typeof num);
                return true;
            }
        }
        if (num in target) {
            log("Num in target");
            target.removeContainer(index);
        }
        if (value) {
            if (value.container) {
                if (value.propertyIndex !== undefined) {
                    value.container[value.propertyName][value.propertyIndex] = null;
                }
                else {
                    value.container[value.propertyName] = null;
                }
            }
            value.container = target._container;
            value.propertyName = target.name;
            value.propertyIndex = index;
            target[index] = value;
        }
        else {
            target.splice(index, 1);
        }
        return true;
    }
};
function part(target, propertyKey) {
    const privatePropertyKey = keyPrefix + propertyKey.toString();
    const getter = function () {
        let result = this[privatePropertyKey];
        if (result === undefined) {
            result = null;
            this[privatePropertyKey] = result;
        }
        return result;
    };
    const setter = function (val) {
        const storedValue = this[privatePropertyKey];
        if (storedValue) {
            storedValue.container = null;
            storedValue.propertyName = "";
            storedValue.propertyIndex = undefined;
        }
        this[privatePropertyKey] = val;
        if (val !== null && val !== undefined) {
            if (val.container !== undefined && val.container !== null) {
                if (val.propertyIndex !== undefined && val.propertyIndex > -1) {
                    val.container[keyPrefix + val.propertyName][val.propertyIndex] = null;
                }
                else {
                    val.container[keyPrefix + val.propertyName] = null;
                }
            }
            val.container = this;
            val.propertyName = propertyKey.toString();
            val.propertyIndex = undefined;
        }
    };
    Reflect.deleteProperty(target, propertyKey);
    Reflect.defineProperty(target, propertyKey, {
        get: getter,
        set: setter
    });
}
exports.part = part;
function listpart(target, propertyKey) {
    const privatePropertyKey = keyPrefix + propertyKey.toString();
    const getter = function () {
        let result = this[privatePropertyKey];
        if (result === undefined) {
            result = new Proxy(new PartArray(propertyKey.toString(), this, []), listPartHandler);
            this[privatePropertyKey] = result;
            result["_M_Container"] = this;
        }
        return result;
    };
    Reflect.deleteProperty(target, propertyKey);
    Reflect.defineProperty(target, propertyKey, {
        get: getter
    });
}
exports.listpart = listpart;
class ModelElementImpl {
}
__decorate([
    mobx_1.observable,
    __metadata("design:type", Object)
], ModelElementImpl.prototype, "container", void 0);
__decorate([
    mobx_1.observable,
    __metadata("design:type", String)
], ModelElementImpl.prototype, "propertyName", void 0);
__decorate([
    mobx_1.observable,
    __metadata("design:type", Number)
], ModelElementImpl.prototype, "propertyIndex", void 0);
exports.ModelElementImpl = ModelElementImpl;
class PartArray extends Array {
    constructor(name, container, items) {
        super(...items);
        Object.setPrototypeOf(this, PartArray.prototype);
        for (let index = 0; index++; index < items.length) {
            items[index].container = this._container;
            items[index].propertyName = this.name;
            items[index].propertyIndex = index;
        }
        this._container = container;
        this.name = name;
    }
    push(...items) {
        log("Part Push: " + items);
        for (let index = 0; index < items.length; index++) {
            items[index].container = this._container;
            items[index].propertyName = this.name;
            items[index].propertyIndex = this.length + index;
        }
        log("-----------------------------------");
        let result = super.push(...items);
        log("+++++++++++++++++++++++++++++");
        return result;
    }
    removeContainer(index) {
        this[index].container = null;
        this[index].propertyIndex = undefined;
        this[index].propertyName = "";
    }
}
exports.PartArray = PartArray;
//# sourceMappingURL=ModelDecorators.js.map