import _forEach from 'lodash/forEach';
import Vue from 'vue';
import _uniq from 'lodash/uniq';
const GetPropertyDescriptor = (o, PropName) => {
    if (o !== undefined) {
        return o.hasOwnProperty(PropName) ?
            Object.getOwnPropertyDescriptor(o, PropName) :
            GetPropertyDescriptor(Object.getPrototypeOf(o), PropName);
    }
    return undefined;
};
export class StoreModule {
    constructor() {
        this._state = {};
        this._mutations = {};
        this._actions = {};
        this._getters = {};
        _forEach(this.getStatePropsNames(), propName => this._state[propName] = this[propName]);
        _forEach(this.getMutationsNames(), mutName => this._mutations[mutName] = this[mutName]);
        _forEach(this.getActionsNames(), actionName => this._actions[actionName] = this[actionName]);
        _forEach(this.getGettersNames(), getterName => {
            const propDescriptor = GetPropertyDescriptor(this, getterName);
            if (propDescriptor !== undefined && propDescriptor.get !== undefined) {
                this._getters[getterName] = propDescriptor.get.bind(this);
            }
        });
        this.initVm();
        this.initStateProxies();
        this.initGettersProxies();
    }
    get state() {
        return this._vm === undefined ? undefined : this._vm._data._state;
    }
    initStateProxies() {
        _forEach(this.getStatePropsNames(), propName => {
            Object.defineProperty(this, propName, {
                get() {
                    return this._state[propName];
                },
                set(val) {
                    this._state[propName] = val;
                }
            });
        });
    }
    initGettersProxies() {
        _forEach(this.getGettersNames(), getterName => {
            Object.defineProperty(this, getterName, {
                get() {
                    return this._vm[getterName];
                }
            });
        });
    }
    collectValuesFromAllPrototypes(obj, propName) {
        if (!obj[propName])
            return [];
        const proto = Object.getPrototypeOf(obj);
        return [
            ...this.collectValuesFromAllPrototypes(proto, propName),
            ...(obj.hasOwnProperty(propName) ? obj[propName] : [])
        ];
    }
    getStatePropsNames() {
        return _uniq(this.collectValuesFromAllPrototypes(this, 'statePropsNames'));
    }
    getMutationsNames() {
        return _uniq(this.collectValuesFromAllPrototypes(this, 'mutationsNames'));
    }
    getActionsNames() {
        return _uniq(this.collectValuesFromAllPrototypes(this, 'actionsNames'));
    }
    getGettersNames() {
        return _uniq(this.collectValuesFromAllPrototypes(this, 'gettersNames'));
    }
    getGlobalGettersNames() {
        return this.globalGettersNames || [];
    }
    initVm() {
        this._vm = new Vue({
            data: { _state: this._state },
            computed: this._getters
        });
    }
}
//# sourceMappingURL=StoreModule.js.map