
import { Instance, SnapshotIn, types } from 'mobx-state-tree';
import {
  extendObject,
  createObject,
  getVariable,
  cloneObject,
  setVariable,
  deleteVariable
} from '../utils/helper';
import { dataMapping } from '../utils/tpl-builtin';
import { SimpleMap } from '../utils/SimpleMap';
import { StoreNode } from './node';
import {
  LionExport,
  rowExport
} from '../renderers/Lion/Table/LionTable/components/LionExport/index';
import { LionLoginAmazon } from '../renderers/Lion/components/Actions/LoginAmazon'
import compact from 'lodash/compact';

export const iRendererStore = StoreNode.named('iRendererStore')
  .props({
    hasRemoteData: types.optional(types.boolean, false),
    data: types.optional(types.frozen(), {}),
    initedAt: 0, // 初始 init 的时刻
    updatedAt: 0, // 从服务端更新时刻
    pristine: types.optional(types.frozen(), {}),
    action: types.optional(types.frozen(), undefined),
    dialogOpen: false,
    dialogData: types.optional(types.frozen(), undefined),
    drawerOpen: false,
    drawerData: types.optional(types.frozen(), undefined),
    // Aug
    lionChildViewOpen: false,
    lionChildViewData: types.optional(types.frozen(), undefined),
    lionChildViewSiblings: types.optional(types.frozen(), []), // 用来保存childView挂载处原本的dom节点
    updateType: '', // 数据更新来源 以判断是否需要保留原数据 当前只有input-table使用
    // Jay
    hiddenIputTable: types.optional(types.frozen(), {}), // 用来保存隐藏的inputTable的数据
    inputTableData: types.optional(types.frozen(), {}), // 用来保存inputTable增删改的数据
    disabledFormItem: types.optional(types.frozen(), {}), // 禁用某些表单选项，例如checkboxex，radio，select目前用到的场景是根据input-table-dynamic的原始数据已有值来禁用
    autoFillObj: types.optional(types.frozen(), {}), // 保存所有表单项的autoFill对象，只是为了给inputTable判断新增数据所用
    replace: types.optional(types.frozen(), {}),// 保存当前表单项的上下对象
  })
  .views(self => ({
    getValueByName(name: string, canAccessSuper: boolean = true) {
      return getVariable(self.data, name, canAccessSuper);
    },

    getPristineValueByName(name: string) {
      return getVariable(self.pristine, name, false);
    }
  }))
  .actions(self => {
    const dialogCallbacks = new SimpleMap<(result?: any) => void>();

    return {
      initData(data: object = {}, skipSetPristine = false) {
        self.initedAt = Date.now();

        !skipSetPristine && (self.pristine = data);
        self.data = data;
      },

      reset() {
        self.data = self.pristine;
      },

      updateData(data: object = {}, tag?: object, replace?: boolean) {
        const prev = self.data;
        let newData;
        if (tag) {
          let proto = createObject((self.data as any).__super || null, tag);
          newData = createObject(proto, {
            ...(replace ? {} : self.data),
            ...data
          });
        } else {
          newData = extendObject(self.data, data, !replace);
        }

        Object.defineProperty(newData, '__prev', {
          value: { ...prev },
          enumerable: false,
          configurable: false,
          writable: false
        });

        self.data = newData;
      },

      // Jay
      // input-table组件增删改时的处理函数
      // name是input-table的name属性值，即作为表单项的name
      changeInputTableValue(value: any, name: string) {
        self.inputTableData = {
          ...self.inputTableData,
          [name]: value
        };
      },
      updateHiddenInputTable(value: any) {
        self.hiddenIputTable = {
          ...self.hiddenIputTable,
          ...value
        }
      },
      // Jay
      // 禁用某些表单选项，例如checkboxex，radio
      abandonFormItem(value: any, name: string) {
        self.disabledFormItem = {
          ...self.disabledFormItem,
          [name]: value
        };
      },

      // Jay
      // 保存所有表单项中的autoFill对象
      setAutoFillObj(obj: { [key: string]: string }) {
        self.autoFillObj = {
          ...self.autoFillObj,
          ...obj
        };
      },

      setUpdateType(type: string = '') {
        self.updateType = type
      },

      changeValue(
        name: string,
        value: any,
        changePristine?: boolean,
        force?: boolean,
        otherModifier?: (data: Object) => void
      ) {
        if (!name) {
          return;
        }

        const origin = getVariable(self.data, name, false);

        if (value === origin && !force) {
          return;
        }

        const prev = self.data;
        const data = cloneObject(self.data);
        if (prev.__prev) {
          // 基于之前的 __prev 改
          const prevData = cloneObject(prev.__prev);
          setVariable(prevData, name, origin);
          Object.defineProperty(data, '__prev', {
            value: prevData,
            enumerable: false,
            configurable: false,
            writable: false
          });
        } else {
          Object.defineProperty(data, '__prev', {
            value: { ...prev },
            enumerable: false,
            configurable: false,
            writable: false
          });
        }

        if (value === undefined) {
          deleteVariable(data, name);
        } else {
          setVariable(data, name, value);
        }

        otherModifier?.(data);

        if (changePristine) {
          const pristine = cloneObject(self.pristine);
          setVariable(pristine, name, value);
          otherModifier?.(pristine);
          self.pristine = pristine;
        }

        if (!data.__pristine) {
          Object.defineProperty(data, '__pristine', {
            value: self.pristine,
            enumerable: false,
            configurable: false,
            writable: false
          });
        }

        self.data = data;
      },

      setCurrentAction(action: object) {
        self.action = action;
      },

      openDialog(ctx: any, additonal?: object, callback?: (ret: any) => void) {
        let proto = ctx.__super ? ctx.__super : self.data;

        if (additonal) {
          proto = createObject(proto, additonal);
        }

        const data = createObject(proto, {
          ...ctx
        });

        if (self.action.dialog && self.action.dialog.data) {
          self.dialogData = dataMapping(self.action.dialog.data, data);

          const clonedAction = {
            ...self.action,
            dialog: {
              ...self.action.dialog
            }
          };
          delete clonedAction.dialog.data;
          self.action = clonedAction;
        } else {
          self.dialogData = data;
        }
        self.dialogOpen = true;
        callback && dialogCallbacks.set(self.dialogData, callback);
      },

      closeDialog(result?: any) {
        const callback = dialogCallbacks.get(self.dialogData);

        self.dialogOpen = false;

        if (callback) {
          dialogCallbacks.delete(self.dialogData);
          setTimeout(() => callback(result), 200);
        }
      },

      openDrawer(ctx: any, additonal?: object, callback?: (ret: any) => void) {
        let proto = ctx.__super ? ctx.__super : self.data;

        if (additonal) {
          proto = createObject(proto, additonal);
        }

        const data = createObject(proto, {
          ...ctx
        });

        if (self.action.drawer.data) {
          self.drawerData = dataMapping(self.action.drawer.data, data);

          const clonedAction = {
            ...self.action,
            dialog: {
              ...self.action.dialog
            }
          };
          delete clonedAction.dialog.data;
          self.action = clonedAction;
        } else {
          self.drawerData = data;
        }
        self.drawerOpen = true;

        if (callback) {
          dialogCallbacks.set(self.drawerData, callback);
        }
      },

      closeDrawer(result?: any) {
        const callback = dialogCallbacks.get(self.drawerData);
        self.drawerOpen = false;

        if (callback) {
          dialogCallbacks.delete(self.drawerData);
          setTimeout(() => callback(result), 200);
        }
      },

      // Aug 打开子页面
      openLionChildView(
        ctx: any,
        env: any,
        additonal?: object,
        callback?: (ret: any) => void
      ) {
        let proto = ctx.__super ? ctx.__super : self.data;

        if (additonal) {
          proto = createObject(proto, additonal);
        }

        const data = createObject(proto, {
          ...ctx
        });

        if (self.action.lionChildView.data) {
          self.lionChildViewData = dataMapping(
            self.action.lionChildView.data,
            data
          );

          const clonedAction = {
            ...self.action,
            lionChildView: {
              ...self.action.lionChildView
            }
          };
          delete clonedAction.lionChildView.data;
          self.action = clonedAction;
        } else {
          self.lionChildViewData = data;
        }

        const { modalContainer } = self.action.lionChildView;

        // 隐藏原层级元素
        const con = modalContainer && document.querySelector(modalContainer);
        const envCon = (() => {
          if (env && env.getModalContainer) {
            if (typeof env.getModalContainer === 'function') {
              return env.getModalContainer();
            }
            return env.getModalContainer;
          }
          return undefined;
        })();
        const node = con || envCon || undefined;
        const children: HTMLElement[] = Array.from(node.children);
        self.lionChildViewSiblings = children;
        children.forEach(child => {
          child.style.display = 'none';
        });

        // 打开新页面
        self.lionChildViewOpen = true;

        if (callback) {
          dialogCallbacks.set(self.lionChildViewData, callback);
        }
      },

      // Aug 关闭子页面
      closeLionChildView(result?: any) {
        const callback = dialogCallbacks.get(self.lionChildViewData);
        self.lionChildViewOpen = false;
        // 显示原层级元素
        setTimeout(() => {
          self.lionChildViewSiblings.forEach((item: HTMLElement) => {
            item.style.display = 'block';
          });
        }, 300);

        if (callback) {
          dialogCallbacks.delete(self.lionChildViewData);
          setTimeout(() => callback(result), 200);
        }
      },

      openLionExport(ctx: any, env: any, normalSelectAll?: boolean, callback?: (result: boolean) => void) {
        env.fetcher(self.action.api, { ...ctx, ...self.data, ...self.data.__super, }).then((res: any) => {
          if (res.status === 0 && res.data !== null) {
            const data = res.data
            if (data.exportType === 2) {
              rowExport(self.action, { ...ctx, ...self.data.__super, ...data, ids: ctx.tempIds }, env).then(res2 => callback && callback(res2))
            } else {
              const obj = createObject(self.data, ctx)
              LionExport(self.action, { ...ctx, ...data }, obj, env, normalSelectAll);
            }
          } else {
            env.alert(res.msg)
          }
        })
      },

      openAmazonLoginPage(ctx: any, env: any) {
        LionLoginAmazon(self.action, ctx, env)
      },

      replaceDialog(data: any) {
        self.replace = data
      }
    };
  });

export type IIRendererStore = Instance<typeof iRendererStore>;
export type SIRendererStore = SnapshotIn<typeof iRendererStore>;
// export type SIRendererStore = typeof iRendererStore.SnapshotType;
