import api from '@/api/editor.api';
import { Module, GetterTree, ActionTree, MutationTree } from 'vuex';
import { cloneDeep } from 'lodash';
import Vue from 'vue';
import {
  SET_PAGE_INFO,
  SET_DRAGABLE,
  COPY_OR_DELETE_PAGE_INFO,
  UPDATE_PAGE_INFO,
  ADD_ELEMENTS,
  SET_CUR_ELE_INDEX,
  SET_CUR_CHILD_INDEX,
  RESET_PAGE_DATA,
  SET_TEMPLATE_LIST,
  SET_PAGE_DATA,
  UPDATE_COMMON_STYLE,
  UPDATE_PAGE_STYLE,
  UPDATE_PAGE_PROPS,
  SET_CUR_RIGHT_TAB_NAME
} from './type';
import { v4 as uuid } from 'uuid';
import RootState from '../../state';
import EditorState, { PageInfo, defaultState, Page, PageElement } from './state';

export default class EditorModule implements Module<EditorState, RootState> {
  state: EditorState;

  getters: GetterTree<EditorState, RootState> = {
    pageData(state: EditorState): Page {
      return state.pageInfo.page as Page;
    },
    pageId(state: EditorState): number | undefined {
      return state.pageInfo.id;
    },
    uuid(state: EditorState): string | undefined {
      return state.pageInfo.uuid;
    },
    pageInfo(state: EditorState): PageInfo {
      return state.pageInfo;
    },
    curRightTabName(state: EditorState): string | null {
      return state.curRightTabName;
    }
  };

  actions: ActionTree<EditorState, RootState> = {
    // pageInfo: 处理过的页面数据 - activity， pageData: 未处理的数据 - editor
    async savePageData({ commit }, { pageInfo, pageData}: { pageInfo: PageInfo, pageData: Page }) {
      if (pageInfo.uuid) {
        await api.updatePage(pageInfo);
        commit(SET_PAGE_INFO, { ...pageInfo, page: pageData });
      } else {
        const res = await api.savePage(pageInfo);
        const { page, ...rest } = res as PageInfo;
        commit(SET_PAGE_INFO, { ...rest, page: pageData });
      }
    },
    async getPageDate({ commit }, condition: number) {
      const res = await api.getPageById(condition);
      const { page, ...rest } = res as PageInfo;
      const pageObj = JSON.parse(page as string);
      commit(SET_PAGE_INFO, { ...rest, page: pageObj });

      const goodsTabs = {};
      (pageObj as Page).elements.forEach((element, idx) => {
        if (element.name === 'cs-goods-tabs' && element?.child?.length) {
          goodsTabs[idx] = cloneDeep(element.child);
          // 逆向循环
          for (let i = element.child.length - 1; i >= 0; i--) {
            commit(COPY_OR_DELETE_PAGE_INFO, { type: 'delete', containerIndex: idx, childIndex: i });
            // this.updatePageData({ type: 'delete', containerIndex: idx, childIndex: i });
          }
        }
      });
      let tempIndex = 0;
      Object.keys(goodsTabs).forEach(key => {
        goodsTabs[key].forEach((child, index) => {
          commit(UPDATE_PAGE_INFO, { containerIndex: +key + 1 + index + tempIndex, data: child, type: 'add' });
          // console.log('parseGoodsTabs', { containerIndex: +key + 1 + index, data: child });
          // this.updatePageInfo({ containerIndex: +key + 1 + index, data: child });
        });
        tempIndex++;
      });
    },
    async getTemplateList({ commit }) {
      const res = await api.getTemplateList({ type: 'template' });
      const handledData = res.map((v, idx) => ({ eleName: `template${idx}`, title: v.pageName, coverImage: v.coverImage, page: v.page }));
      // todo 解析数据
      commit(SET_TEMPLATE_LIST, handledData);
    },
    async setTemplateInfo({commit}, condition) {
      const res = await api.getPageById(condition);
      const { page } = res as PageInfo;
      const { pageInfo } = cloneDeep(defaultState);
      const pageObj = JSON.parse(page as string);
      commit(SET_PAGE_INFO, { ...pageInfo, page: pageObj });
      const goodsTabs = {};
      (pageObj as Page).elements.forEach((element, idx) => {
        if (element.name === 'cs-goods-tabs' && element?.child?.length) {
          goodsTabs[idx] = cloneDeep(element.child);
          // 逆向循环
          for (let i = element.child.length - 1; i >= 0; i--) {
            commit(COPY_OR_DELETE_PAGE_INFO, { type: 'delete', containerIndex: idx, childIndex: i });
            // this.updatePageData({ type: 'delete', containerIndex: idx, childIndex: i });
          }
        }
      });
      let tempIndex = 0;
      Object.keys(goodsTabs).forEach(key => {
        goodsTabs[key].forEach((child, index) => {
          commit(UPDATE_PAGE_INFO, { containerIndex: +key + 1 + index + tempIndex, data: child, type: 'add' });
          // console.log('parseGoodsTabs', { containerIndex: +key + 1 + index, data: child });
          // this.updatePageInfo({ containerIndex: +key + 1 + index, data: child });
        });
        tempIndex++;
      });
    },
    setDragable({ commit }, condition) {
      commit(SET_DRAGABLE, condition);
    },
    resetPageData({ commit }, condition) {
      const { pageInfo, curEleIndex, curChildIndex } = cloneDeep(defaultState);
      commit(SET_PAGE_INFO, pageInfo);
      commit(SET_CUR_ELE_INDEX, curEleIndex);
      commit(SET_CUR_CHILD_INDEX, curChildIndex);
    }
  };

  mutations: MutationTree<EditorState> = {
    [SET_PAGE_INFO](state, data) {
      state.pageInfo = data;
    },
    [SET_DRAGABLE](state, data) {
      state.gridLayout.draggable = data;
    },
    [SET_CUR_ELE_INDEX](state, curEleIndex) {
      state.curEleIndex = curEleIndex;
    },
    [SET_CUR_CHILD_INDEX](state, curChildIndex) {
      state.curChildIndex = curChildIndex;
    },
    [SET_CUR_RIGHT_TAB_NAME](state, curRightTabName) {
      state.curRightTabName = curRightTabName;
    },
    [SET_TEMPLATE_LIST](state, data) {
      state.templateList = data;
    },
    [SET_PAGE_DATA](state, data) {
      state.pageInfo.page = data;
    },
    [COPY_OR_DELETE_PAGE_INFO](state, { type, containerIndex, childIndex }) {
      const page = (state.pageInfo.page as Page).elements;
      if (type === 'delete') {
        if (childIndex || childIndex === 0) {
          page[containerIndex].child.splice(childIndex, 1);
        } else {
          page.splice(containerIndex, 1);
        }
        state.curEleIndex = null;
        state.curChildIndex = null;
      } else if (type === 'copy') {
        let eleCopyed = {} as PageElement;
        const newId = uuid().slice(19);
        if (childIndex || childIndex === 0) {
          eleCopyed = cloneDeep(page[containerIndex].child[childIndex] || {});
          eleCopyed.id = newId;
          eleCopyed.point.i = newId;
          const { left, top } = eleCopyed.commonStyle;
          page[containerIndex].child.push({ ...eleCopyed, commonStyle: { ...eleCopyed.commonStyle, left: left + 10, top: top + 10 } });
        } else {
          eleCopyed = cloneDeep(page[containerIndex] || {});
          eleCopyed.id = newId;
          eleCopyed.point.i = newId;
          page.push({ ...eleCopyed, point: { ...eleCopyed.point }});
        }
      }
    },
    [UPDATE_PAGE_INFO](state, { containerIndex, childIndex, data, type }) {
      const page = (state.pageInfo.page as Page).elements;
      if (childIndex || childIndex === 0) {
        page[containerIndex].child.splice(childIndex, 1, data);
      } else if (type === 'add') {
        page.splice(containerIndex, 0, data);
      } else {
        page.splice(containerIndex, 1, data);
      }
    },
    [UPDATE_COMMON_STYLE](state, {containerIndex, childIndex, data}) {
      const page = (state.pageInfo.page as Page).elements;
      if (childIndex || childIndex === 0) {
        Vue.set(page[containerIndex].child[childIndex], 'commonStyle', data);
      } else {
        Vue.set(page[containerIndex], 'commonStyle', data);
      }
    },
    [UPDATE_PAGE_STYLE](state, { data }) {
      (state.pageInfo.page as Page).commonStyle = data;
    },
    [UPDATE_PAGE_PROPS](state, { data }) {
      (state.pageInfo.page as Page).props = data;
    },
    [ADD_ELEMENTS](state, { containerIndex, data }) {
      const page = (state.pageInfo.page as Page).elements;
      if (containerIndex || containerIndex === 0) {
        page[containerIndex].child.push(data);
      } else {
        page.push(data);
      }
    },
  };

  constructor(initState: EditorState = cloneDeep(defaultState)) {
    this.state = initState;
  }
}