import {
  // deepCopy,
  calcSum,
  getElementId,
  objAssign,
  randomCode,
} from "../../card/plugins/utils";

const state = {
  pageConfig: {},
  curElement: {},
  curDragElement: {},
  curPage: {},
  curPageNo: 0,
  pages: [],
  topics: [],
  insetTarget: {},
  openElementEditDialog: false,
  cover: [],
};

const mutations = {
  setPageConfig(state, pageConfig) {
    state.pageConfig = Object.assign({}, state.pageConfig, pageConfig);
  },
  setCurElement(state, curElement) {
    state.curElement = curElement;
  },
  setCurDragElement(state, curDragElement) {
    state.curDragElement = curDragElement;
  },
  setCurPage(state, curPageNo) {
    const pageNo = state.pages[curPageNo] ? curPageNo : 0;
    state.curPage = state.pages[pageNo];
    state.curPageNo = pageNo;
  },
  setCurPageNo(state, curPageNo) {
    state.curPageNo = curPageNo;
  },
  setPages(state, pages) {
    state.pages = pages;
  },
  setTopics(state, topics) {
    state.topics = topics;
  },
  switchTopics(state, pageType) {
    let topics = [];
    if (pageType === "cover") {
      state.pages[0].columns.forEach((column) => {
        topics.push(...column.elements);
      });
    } else {
      state.pages
        .filter((p) => p.pageType !== "cover")
        .forEach((page) => {
          page.columns.forEach((column) => {
            topics.push(...column.elements);
          });
        });
    }
    state.topics = topics;
  },
  setInsetTarget(state, insetTarget) {
    state.insetTarget = insetTarget;
  },
  addPage(state, page) {
    state.pages.push(page);
  },
  modifyPage(state, page) {
    state.pages.splice(page._pageNo, 1, page);
  },
  setOpenElementEditDialog(state, openElementEditDialog) {
    state.openElementEditDialog = openElementEditDialog;
  },
  initState(state) {
    state.curElement = {};
    state.curDragElement = {};
    state.curPage = {};
    state.curPageNo = 0;
    state.topics = [];
    state.pages = [];
    state.openElementEditDialog = false;
  },
};

const fetchElementPositionInfos = (element, topics) => {
  return topics.findIndex((item) => item.id === element.id);
};

const findElementById = (id, topics) => {
  let curElement = null;
  topics.forEach((element) => {
    if (curElement) return;
    if (element.id === id) {
      curElement = element;
      return;
    }

    if (element["elements"]) {
      element["elements"].forEach((elem) => {
        if (elem.id === id) curElement = elem;
      });
    }
  });
  return curElement;
};

const checkElementisCovered = (id, type) => {
  const elementDom = document.getElementById(id);
  if (!elementDom) return;

  if (type === "PANE_BOX") {
    const limitHeight = elementDom.offsetHeight;
    const limitWidth = elementDom.offsetWidth;

    let elementHeights = [],
      elementWidths = [];
    const elementChildren = elementDom.querySelector(
      ".elem-pane-box-elements"
    ).childNodes;

    if (!elementChildren) return;
    elementChildren.forEach((node) => {
      if (!node.className || !node.className.includes("elem-pane-box-element"))
        return;

      elementHeights.push(
        node.firstChild.offsetHeight + node.firstChild.offsetTop
      );
      elementWidths.push(
        node.firstChild.offsetWidth + node.firstChild.offsetLeft
      );
    });

    // console.log(elementWidths, limitWidth);
    return (
      elementHeights.some((item) => item > limitHeight) ||
      elementWidths.some((item) => item > limitWidth)
    );
  }

  return elementDom.offsetHeight < elementDom.firstChild.offsetHeight;
};

const actions = {
  changePage({ state, commit }, pageNo) {
    const lastPageType = state.pages[state.curPageNo].pageType;
    commit("setCurPage", pageNo);

    if (!state.pageConfig.showCover) return;
    if (lastPageType !== "cover" && state.curPage.pageType !== "cover") return;

    commit("switchTopics", state.curPage.pageType);
  },
  directChangePage({ state, commit }, pageNo) {
    commit("setCurPage", pageNo);
    commit("switchTopics", state.curPage.pageType);
  },
  modifyPagesInfo({ state, commit }, data) {
    for (let i = 0; i < state.pages.length; i++) {
      state.pages[i] = objAssign(state.pages[i], data);
    }
    commit("setCurPage", state.curPageNo);
  },
  actElementById({ state, commit }, id) {
    const curElement = findElementById(id, state.topics);
    if (!curElement) return;

    commit("setCurElement", curElement);
  },
  // side   --------->
  // 新增元素
  addSideElement({ state, commit }, element) {
    state.pages[state.curPageNo].sides.push(element);
    state.curPage = state.pages[state.curPageNo];
    commit("setCurElement", element);
  },
  // 修改元素
  modifySideElement({ state }, element) {
    element.key = randomCode();
    const pos = fetchElementPositionInfos(
      element,
      state.pages[state.curPageNo].sides
    );
    if (pos === -1) return;
    state.pages[state.curPageNo].sides.splice(pos, 1, element);
  },
  // 删除元素
  removeSideElement({ state, commit }, element) {
    const pos = fetchElementPositionInfos(
      element,
      state.pages[state.curPageNo].sides
    );
    if (pos === -1) return;
    state.pages[state.curPageNo].sides.splice(pos, 1);

    commit("setCurElement", {});
  },
  // column --------->
  // 新增元素
  addElement({ state, commit }, element) {
    state.topics.push(element);
    commit("setCurElement", element);
  },
  // 修改元素
  modifyElement({ state }, element) {
    element.key = randomCode();
    const pos = fetchElementPositionInfos(element, state.topics);
    if (pos === -1) return;
    state.topics.splice(pos, 1, element);
  },
  // 修改编辑框包含元素
  modifyElementChild({ state, commit }, element) {
    const pos = fetchElementPositionInfos(element.container, state.topics);
    const columnElements = state.topics[pos].elements;
    const childIndex = columnElements.findIndex(
      (item) => item.id === element.id
    );
    element.id = getElementId();
    if (childIndex === -1) {
      columnElements.push(element);
    } else {
      columnElements.splice(childIndex, 1, element);
    }

    commit("setCurElement", element);
  },
  // 粘贴编辑框内的元素
  pasteElementChild({ state }, { curElement, pasteElement }) {
    let element = {
      id: curElement.container ? curElement.container.id : curElement.id,
    };
    const pos = fetchElementPositionInfos(element, state.topics);
    if (pos === -1) return;

    element = state.topics[pos];
    const newElement = Object.assign({}, pasteElement, {
      id: getElementId(),
      container: {
        id: element.id,
        type: element.type,
      },
    });
    element.elements.push(newElement);
  },
  // 删除编辑框 --------------->
  removeElement({ state, commit }, element) {
    const pos = fetchElementPositionInfos(element, state.topics);
    state.topics.splice(pos, 1);

    commit("setCurElement", {});
  },
  // 删除编辑框包含元素 --------------->
  removeElementChild({ state, commit }, element) {
    const pos = fetchElementPositionInfos(element.container, state.topics);
    const columnElements = state.topics[pos].elements;
    const childIndex = columnElements.findIndex(
      (item) => item.id === element.id
    );
    columnElements.splice(childIndex, 1);

    commit("setCurElement", {});
  },
  // 重构页面
  resetElementProp({ state }, isResetId = false) {
    state.topics.forEach((element) => {
      const elementDom = document.getElementById(element.id);
      if (elementDom) {
        element.h = elementDom.offsetHeight;
        element.w = elementDom.offsetWidth;
      }
      if (isResetId) {
        element.id = getElementId();
        if (element.elements && element.elements.length) {
          element.elements.forEach((child) => {
            child.container.id = element.id;
          });
        }
      }
    });
  },
  rebuildPages({ state, commit }) {
    const pageInfo = state.pages[0];
    const { columnNumber } = pageInfo;
    // 更新元件最新的高度信息
    // 整理所有元件
    state.topics.forEach((element) => {
      const elementDom = document.getElementById(`preview-${element.id}`);

      if (elementDom) {
        element.h = elementDom.offsetHeight;
        element.w = elementDom.offsetWidth;
        // 编辑框需要手动设置高度。
        element.isCovered = checkElementisCovered(
          `preview-${element.id}`,
          element.type
        );
      }
    });

    // 动态计算每列可以分配的元件
    const columnHeight = document.getElementById("topic-column").offsetHeight;
    let columns = [];
    let curColumnElements = [];
    let curColumnHeight = 0;

    const initCurColumnElements = () => {
      curColumnElements = [];
      curColumnHeight = 0;
    };

    // 放入元素通用流程
    const pushElement = (element) => {
      let elementList = [element];

      const elementHeight = calcSum(elementList.map((elem) => elem.h));
      if (curColumnHeight + elementHeight > columnHeight) {
        // 当前栏第一个元素高度超过一栏时，不拆分，直接放在当前栏。
        // 解决可能空栏的情况
        const curElementIsFirst = !curColumnElements.length;
        if (curElementIsFirst) {
          curColumnElements = [...curColumnElements, ...elementList];
          curColumnHeight += elementHeight;
        } else {
          columns.push([...curColumnElements]);
          initCurColumnElements();
          pushElement(element);
        }
      } else {
        curColumnElements = [...curColumnElements, ...elementList];
        curColumnHeight += elementHeight;
      }
    };

    // 批量添加所有元素。
    initCurColumnElements();
    state.topics.forEach((element) => {
      pushElement(element);
    });

    // 最后一栏的处理。
    columns.push([...curColumnElements]);
    if (state.curPage.pageType === "cover") {
      // 封面只能有一页
      columns = columns.slice(0, 1 * columnNumber);
      for (let i = 0; i < columnNumber; i++) {
        state.pages[0].columns[i].elements = columns[i] || [];
      }
    } else {
      // 正文只能有两页
      columns = columns.slice(0, 2 * columnNumber);
      let cno = 0;
      for (let pNo = 0; pNo < 2; pNo++) {
        let pageNo = state.pageConfig.showCover ? pNo + 1 : pNo;
        for (let columnNo = 0; columnNo < columnNumber; columnNo++) {
          state.pages[pageNo].columns[columnNo].elements = columns[cno++] || [];
        }
      }
    }

    commit("setCurPage", state.curPageNo);
    commit("switchTopics", state.curPage.pageType);
  },
};

export { checkElementisCovered, findElementById };

export default {
  namespaced: true,
  state,
  mutations,
  actions,
};
