import { isString, isObject, merge } from '../util';
import dirtyActions from '../action/dirty';
import { modelActions } from '../action/event';

/**
 * Model基类
 * 
 * @class Model
 */
class Model {

    __dirty = true;

    _updateTime = 0;

    constructor(option = {}, parentModel, globalModel, global) {
        this.option = option;
        this.parentModel = parentModel;
        this.globalModel = globalModel;
        this.global = global;
    }

    /**
     * 标记为脏,将被更新
     * 
     * @param {Object} action 触发dirty的事件
     */
    dirty(action) {
        let { globalModel } = this;
        // console.log(`${this.type}_${this.index}准备设置为dirty!`, action);
        if (!action || this.shouldModelDirty(action, this, globalModel)) {
            // console.log(`${this.type}_${this.index}设置为了dirty!--------------`, action);
            this.__dirty = true;
            globalModel && globalModel !== this && globalModel.dirty(this, action);

            this.global.dispatchAction(this, modelActions.willUpdate, { action, model: this });
            return true;
        } else {
            return false;
        }
    }

    /**
     * 是否需要设置为dirty
     * 
     * @param {Object} action 触发dirty的事件
     * @param {Object} model 组件model
     * @param {Object} globalModel globalModel
     * @returns {boolean} 是否需要标记dirty
     */
    shouldModelDirty(action, model, globalModel) {
        return true;
    }

    /**
     * 子类需实现update方法
     */
    update() { }

    beforeUpdate() { }

    afterUpdate() { }

    /**
     * 内部实际调用的update方法
     * 
     * @param {bool} force 是否强制更新
     * @private
     */
    __update(force) {
        if (this.isDirty() || force) {
            this.beforeUpdate(force);
            this.update(force);
            this.__dirty = false;
            this._updateTag = ++this._updateTime + '|' + this.id; // 设置tag
            // console.log(`${this.type}_${this.index}更新了!依赖我的也会更新`, this.supports);
            this.global.dispatchAction(this, modelActions.didUpdate, { model: this, option: this._option });
            this.afterUpdate(force);
        }
    }

    /**
     * 是否为dirty
     * 
     * @returns {boolean} 是否为dirty
     */
    isDirty() {
        return this.__dirty;
    }

    /**
     * 获取实际option
     * 
     * @param {string} [key] 获取option内的key属性,若不传返回全部option
     * @returns {any} 返回key对应的属性
     */
    get(key) {
        if (key) {
            return this._option[key];
        } else {
            return this._option;
        }
    }

    /**
     * 设置option
     * TODO 设置的option与之前相同时
     * 
     * @param {string|Object} key 属性名或者属性对象
     * @param {any} [value] 属性内容
     */
    set(key, value) {
        if (isString(key) && (this._option[key] !== value || typeof value === 'object')) {
            this._option[key] = value;
            this.dirty({
                type: dirtyActions.setOption,
                payload: {
                    [key]: value,
                }
            });
        } else if (isObject(key)) {
            merge(this._option, key, true);
            this.dirty({
                type: dirtyActions.mergeOption,
                payload: key
            });
        }
    }
}

export default Model;