import { kebabCase, maxBy, matches } from 'lodash';
import { Getter, Action, State, Mutation } from 'vuex-class';
import { Mixins, Component, Watch, Provide } from 'vue-property-decorator';
import VueGridLayout from 'vue-grid-layout';
import config from '@config/index';
import TransformStyleMixin from '@page/mixins/transformStyle.mixin';
import ContextMenuMixin from '@editor/mixins/contextMenu.mixin';
import GoodsTabsMixin from '@editor/mixins/goodsTabs.mixin';
import AutoSaveMixin from '@editor/mixins/autoSave.mixin';
import BasicPageFormModal from '@editor/component/BasicPageFormModal/index.vue';
import RecordModal from '@editor/component/RecordModal/index.vue';
import MaterialMenu from '@editor/component/MaterialMenu/index.vue';
import DynamicFormTabs from '@editor/component/DynamicFormTabs/index.vue';
import localStorage from '@service/localStorage.service';
import EventBus from '@service/eventBus.service';
import { getStyle } from '@service/utils.service';
import OperationPanel from '@editor/component/OperationPanel/index.vue';
import type { PageInfo, Page, GridLayout } from '../../../store/modules/editor/state';
import { pickAllScheme, separateAllScheme } from '../../../store/modules/editor/scheme';

@Component({components: { GridLayout: VueGridLayout.GridLayout,
  GridItem: VueGridLayout.GridItem, BasicPageFormModal, RecordModal, MaterialMenu, DynamicFormTabs, OperationPanel }, name: 'DashBoard'})
export default class DashBoard extends Mixins(ContextMenuMixin, GoodsTabsMixin, TransformStyleMixin, AutoSaveMixin) {

  get layout() {
    return this.pageData.elements.map(v => v.point);
  }
  @Mutation('ADD_ELEMENTS') addElements;
  @Mutation('SET_CUR_ELE_INDEX') setCurEleIndex;
  @Mutation('SET_CUR_CHILD_INDEX') setCurChildIndex;
  @Mutation('SET_PAGE_INFO') setPageInfo;
  @Mutation('SET_PAGE_DATA') setPageData;
  @Mutation('UPDATE_PAGE_STYLE') setPageStyle;
  @Mutation('UPDATE_PAGE_PROPS') setPageProps;
  @Mutation('SET_CUR_RIGHT_TAB_NAME') setRightTabName;
  @Action('resetPageData') resetPageData;
  @Action('savePageData') savePageData;
  @Action('getPageDate') getPageDate;
  @Action('getTemplateList') getTemplateList;
  @Action('setTemplateInfo') setTemplateInfo;
  @Getter('uuid') uuid!: string;
  @Getter('pageData') pageData;
  @State(state => state.editor.gridLayout) gridLayout?: GridLayout;
  @State(state => state.editor.curEleIndex) curEleIndex!: number | null;
  @State(state => state.editor.curChildIndex) curChildIndex!: number | null;

  @Provide() editor = this;

  isEditor: boolean = true;
  isCollapsed: boolean = true;
  isDragIn: boolean = false;
  isDraging: boolean = false;
  showSubmitPopup: boolean = false;
  inTheSave: boolean = false;
  searchBarComNum: number = 0;

  get pageDataInject() {
    return this.pageData;
  }

  async created() {
    const { pageId, templateId } = this.$route.params;
    this.resetPageData();
    if (pageId) {
      await this.getPageDate({ pageId });
    } else if (templateId) {
      await this.setTemplateInfo({ pageId: templateId });
    }
    this.getTemplateList();
    // 历史记录
    this.showRecord();
    this.autoSave();
  }

  beforeRouteLeave(to, from, next) {
    console.log('beforeRouteLeave');
  }

  async save(type: 'preview' | 'save', pageConfig) {
    try {
      const user = localStorage.get('user');
      const isCreate = !!this.uuid;
      if (!type) {
        this.showSubmitPopup = true;
      } else {
        this.pageData.elements.sort((a, b) => a.point.y - b.point.y);
        // 处理商品标签组件
        let pageData = this.handleTabsRepaetCom();
        pageData = this.handleComAchorScrollEnable();
        pageData = this.handleGoodsTabs();
        pageData = this.handleCouponIds();
        const { pageName, pageDescribe, pageKeywords, coverImage, isPublish, isTemplate, shareCoverImage, shareOpenMethod, diversion } = pageConfig;
        // ！diversion shareCoverImage shareOpenMethod没有作为单独的sql字段存储下来，只是单纯的存储到的redis中
        // 目前对此打了补丁，存放到page的props中
        pageData.props.diversion = diversion;
        pageData.props.shareCoverImage = shareCoverImage;
        pageData.props.shareOpenMethod = shareOpenMethod;
        // pageData.scheme = pickAllScheme(pageData.elements);
        // 如果存在sheme， 移除页面中的sacheme
        delete pageData.scheme;
        separateAllScheme(pageData.elements);
        const pageInfo = { diversion, page: JSON.stringify(pageData), author: user?.account, isPublish,  pageName, pageDescribe, pageKeywords, coverImage, isTemplate, shareCoverImage, shareOpenMethod } as pageInfo;
        if (this.uuid) { pageInfo.uuid = this.uuid; }
        const requestPageData = this.handleCouponIds();
        await this.savePageData({ pageInfo, pageData: requestPageData });
        if (this.uuid) { await this.getPageDate({ pageId: this.uuid }); }
        this.showSubmitPopup = false;
        // 清除新增数据时的缓存
        if (!isCreate) { this.removeDefaultCache(); }
        if (type === 'preview') {
          window.open(`${config.h5Host}/activity/${this.uuid}?tenantId=${this.pageInfo.tenantId}`);
        } else {
          this.$Notice.success({ title: '保存成功！' });
        }
      }
    } catch (e) {
      this.showSubmitPopup = false;
      this.$Notice.error({ title: '提示', desc: e?.message || '出现未知错误！'});
    } finally {
      this.inTheSave = false;
    }
  }

  async preview() {
    this.inTheSave = true;
    (this.$refs.basicPageForm as any).preview();
  }

  exit() {
    this.$router.back();
  }

  handleElementClick(curEleIndex?: number | null, curChildIndex?: number | null) {
    console.log('handleElementClick - DashBoard', curEleIndex, curChildIndex);
    this.toggle(false);
    this.setCurEleIndex(curEleIndex);
    this.setCurChildIndex(curChildIndex);
    this.setRightTabName('组件设置');
  }

  handlePageSetClick() {
    this.toggle(false);
    this.setRightTabName('页面设置');
  }

  toggle(val) {
    this.isCollapsed = val;
  }

  dragenter() {
    this.isDragIn = true;
  }

  dragleave() {
    this.isDragIn = false;
  }

  dragover(event) {
    if (event?.target?.children?.[0]?.classList.contains('freedom')) {
      event.dataTransfer.dropEffect = 'move';
    } else {
      event.dataTransfer.dropEffect = 'copy';
    }
  }

  modProps(props, ele, type) {
    if (ele === 'page') {
      if (type === 'commonStyle') {
        this.setPageStyle({ data: props });
      } else if (type === 'props') {
        this.setPageProps({ data: props });
      }
    } else if (ele === 'component') {
      let currentEle = {};
      if (this.curEleIndex !== null) {
        if (this.curChildIndex !== null) {
          currentEle = this.pageData.elements[this.curEleIndex].child[this.curChildIndex];
          this.updatePageInfo({ containerIndex: this.curEleIndex, childIndex: this.curChildIndex, data: { ...currentEle, props: { ...currentEle.props, ...props } } });
        } else {
          currentEle = this.pageData.elements[this.curEleIndex];
          this.updatePageInfo({ containerIndex: this.curEleIndex, data: { ...this.pageData.elements[this.curEleIndex], props: { ...currentEle.props, ...props } } });
        }
      }
    }
  }

  drops(event) {
    this.isDragIn = false;
    this.isCollapsed = false;
    const data = JSON.parse(event.dataTransfer.getData('text'));
    const { layerX: left, layerY: top } = event;
    const target = event?.target?.children?.[0]?.children?.[0] || {};
    event.dataTransfer.clearData();
    // template
    if (data.template) {
      this.setPageData(JSON.parse(data.template));
      this.handleElementClick(null, null);
    // freedom
    } else if (target?.classList?.contains('freedom-body')) {
      const { y: curY } = this.pageData.elements[target?.dataset?.index].point;
      const scrollTop = this.layout.reduce((pre, cur) => {
        if (cur.y < curY) {
          return pre + cur.h * this.gridLayout.rowHeight;
        }
        return pre;
      }, 0);
      this.addElements({ containerIndex: target?.dataset?.index, data: { ...data, commonStyle: { position: 'absolute', left, top: top - scrollTop } } });
      this.handleElementClick(+target?.dataset?.index, this.pageData.elements[target?.dataset?.index].child.length - 1);
    // component
    } else {
      const y = Math.floor(top / this.gridLayout.rowHeight);
      this.addEleFilter({ data: {...data, point: { ...data.point, y } }});
      this.handleElementClick(this.pageData.elements.length - 1, null);
    }
    // 调整组件高度
    this.$nextTick(() => this.adjustHeight());
  }

  addEle(data) {
    if (data.template) {
      this.setPageData(JSON.parse(data.template));
      this.handleElementClick(null, null);
    } else {
      const y = getStyle(document.querySelector('.vue-grid-layout'), 'height');
      this.addEleFilter({ data: {...data, point: { ...data.point, y } }});
      this.handleElementClick(this.pageData.elements.length - 1, null);
    }
    // 调整组件高度
    this.$nextTick(() => this.adjustHeight());
  }
  // 限制组件添加
  addEleFilter(el) {
    // 限制searchNav只添加一个
    if (el.data.name === 'cs-search-bar' && this.hasSearchBarCom) {
      this.$Notice.warning({
        title: '搜索框只能添加一个'
      });
      return;
    }
    // 限制floor-nav只添加一个，同时添加后goods-tabs会取消锚点滚动
    if (el.data.name === 'cs-floor-nav') {
      if (this.hasFloorNavCom) {
        this.$Notice.warning({
          title: '楼层导航目前只支持添加一个'
        });
        return;
      } else {
        this.$Message.error({
          content: '楼层导航添加后，商品导航中的锚点滚动将会无效',
          duration: 10
        });
      }
    }
    if (el.data.name === 'cs-snap-up') {
      if (this.hasSnapUpCom) {
        this.$Notice.warning({
          title: '抢购组件目前只支持添加一个'
        });
        return;
      }
    }
    // 添加多个goods-tabs会取消锚点滚动
    if (el.data.name === 'cs-goods-tabs') {
      if (this.hasGoodsNavCom) {
        this.$Message.error({
          content: '添加多个商品导航后，商品导航中的锚点滚动将会无效',
          duration: 10
        });
      } else if (this.hasFloorNavCom) {
        this.$Message.error({
          content: '已添加楼层导航后，商品导航中的锚点滚动将会无效',
          duration: 10
        });
      }
    }
    this.addElements(el);
  }

  resizedEvent(i, h, w) {
    const index = this.pageData.elements.findIndex(ele => ele.point.i === i);
    this.updatePageInfo({ containerIndex: index, data: { ...this.pageData.elements[index], point: { ...this.pageData.elements[index].point, w, h } } });
  }

  movedEvent(i, newX, newY) {
    EventBus.$emit('component-moved');
  }

  /**
   * 调整自由容器子元素宽高及边框原点位置
   * @param {[type]} type 尺寸类型
   */
  resizedChildEvent(type) {
    const containerEle = this.$refs[`freedomContainer${containerIndex}`];
    // const containerEle = this.$refs.container[(this.curEleIndex as number)];
    containerEle.setChildSize(type);
    containerEle.setPointStyle();
  }
}