import { BindAll } from 'lodash-decorators';
import { action, computed, isObservable, observable, toJS } from 'mobx';
import { persist } from 'mobx-persist';
import { lastValueFrom, Subject } from 'rxjs';
import { AuthOptions } from './options';
import lodash from 'lodash';
export interface IInfoOptions {
    StorageKey: string
}
@BindAll()
export class InfoController<T = any> {
    constructor(private options: IInfoOptions = { StorageKey: 'mamba-auth-info', }) {
        this.createHydrate()
    }
    /**
    * 持久化初始化完成 Subject
    * @type {Promise<any>}
    * @memberof ControllerUser
    */
    protected readonly HydrateSubject = new Subject<Boolean>();
    /**
    * 持久化初始化完成 Promise
    * @type {Promise<any>}
    * @memberof ControllerUser
    */
    get HydrateAsync(): Promise<this> {
        return lastValueFrom(this.HydrateSubject, { defaultValue: undefined });
    }
    /**
    * 异步 HydrateSubject 已经完成
    * @readonly
    * @memberof PortalAuthController
    */
    get HydrateisStopped() {
        return this.HydrateSubject.isStopped
    }
    get StorageKey() {
        return `_Auth_${this.options.StorageKey}`
    }
    /**
     * 数据存储对象
     * @protected
     * @type {T}
     * @memberof InfoController
     */
    @observable
    protected _value: T = undefined;
    /**
     * 最后一次更新 值 HydrateisStopped 未完成前 存储 用于对比变化
     * @protected
     * @memberof AuthController
     */
    protected lastValue = undefined;
    /**
     * 外部可访问对象
     * @readonly
     * @type {T}
     * @memberof InfoController
     */
    @computed
    get value(): T {
        return this._value
    }
    /**
     * 保存 Token
     * @param _AccessToken 
     * @returns 
     */
    @action
    onSave(value: T) {
        try {
            AuthOptions.writeCheck()
            if (lodash.isEqual(value, this._value)) {
                return AuthOptions.log('Save Value 无值改变', value, '=>', this._value)
            }
            if (isObservable(value)) {
                value = toJS(value)
            }
            if (!this.HydrateisStopped) {
                this.lastValue = value;
            }
            this._value = value
        } catch (error) {
            AuthOptions.log('error', error)
        }
    }
    /**
     * 清理所有的登录信息
     * @return {*} 
     * @memberof AuthController
     */
    onClear() {
        this.onSave(undefined)
    }
    /**
   * 创建持久化存储
   * @memberof BaseModel
   */
    protected async createHydrate() {
        try {
            if (!AuthOptions.browser) {
                throw '非浏览器环境 不进行 Hydrate'
            }
            const Hydrate = AuthOptions.createHydrate()
            persist({
                _value: {
                    type: 'object',
                }
            })(this);
            AuthOptions.log(`Info ${this.StorageKey}`, this)
            await Hydrate(this.StorageKey, this);
            if (!lodash.isEmpty(this.lastValue) && !lodash.isEqual(this._value, this.lastValue)) {
                AuthOptions.log(`Info ${this.StorageKey} LastValue`, this, this.lastValue)
                this.onSave(this.lastValue);
            }
            this.HydrateSubject.next(true)
            this.HydrateSubject.complete()
        } catch (error) {
            if (AuthOptions.browser) {
                AuthOptions.log('error', error)
            }
            this.HydrateSubject.next(false)
            this.HydrateSubject.complete()
        }
    }
}
