<template>
  <div class="poster-editor-comp" :id="editorUid">
    <div class="main-pane" :style="{ minHeight: 720 * dZoom + 58 + 'px' }">
      <div class="header-ct">
        <div class="left">
          <el-tooltip effect="dark" content="撤销" placement="top-start">
            <el-button
              :disabled="!canClickPrev"
              @click="getHistory(-1)"
              type="text"
            >
              <Icon
                style="color:#fff"
                :active="canClickPrev"
                class="m-r-16"
                icon="Undo"
              ></Icon>
            </el-button>
          </el-tooltip>
          <el-tooltip effect="dark" content="前进" placement="top-start">
            <el-button
              :disabled="!canClickNext"
              @click="getHistory(1)"
              type="text"
            >
              <Icon :active="canClickNext" class="mirror" icon="Undo"></Icon>
            </el-button>
          </el-tooltip>
        </div>
        <div class="center">
          轻点元素开始编辑
        </div>
        <div class="right">
          <el-button size="small" @click="resetItme">重置</el-button>
          <el-button size="small" @click="submitImg">保存并返回</el-button>
        </div>
      </div>
      <draggable
        ref="posterContent"
        v-bind="getOptions()"
        @end="isDragging = false"
        @start="isDragging = true"
        :style="{
          width: dZoom * page.width + 'px',
          height: dZoom * page.height + 'px',
          backgroundColor: value.background.color
        }"
        class="poster-content m-b-16"
        tag="div"
      >
        <div>
          <vue-canvas-poster
            v-show="true"
            :painting="painting"
            @success="success"
            @fail="fail"
          ></vue-canvas-poster>
        </div>
        <img
          v-show="value.background.img"
          class="bg-puppet"
          :src="value && value.background.img"
        />
        <widget
          :class="{ disabled: !item.active }"
          @click.native="handleActiveWidget(item)"
          @dragstart.native="dragStart($event, item)"
          @dragend.native="dragEnd($event, item, index)"
          @modify="pushHistory"
          :widget-data="item"
          :order="index"
          :page="page"
          :d-zoom="dZoom"
          :key="item.uuid"
          v-for="(item, index) in widgetList"
        >
        </widget>
      </draggable>
    </div>
    <div class="right-pane">
      <el-tabs>
        <el-tab-pane label="当前组件">
          <div v-if="activeWidget" class="style-setting-ct">
            <el-collapse v-model="activeNames">
              <el-collapse-item
                v-if="activeWidget.setDataRange.content.show"
                title="文本内容"
                name="1"
              >
                <div class="style-config m-r-16">
                  <el-input
                    v-model="activeWidget.content"
                    type="textarea"
                  ></el-input>
                </div>
              </el-collapse-item>
              <el-collapse-item
                v-if="activeWidget.setDataRange.box.show"
                title="组件样式"
                name="2"
              >
                <div class="style-config">
                  <span class="label">
                    X
                  </span>
                  <el-input-number
                    :precision="0"
                    v-model="activeWidget.style.left"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                  <span class="label">
                    Y
                  </span>
                  <el-input-number
                    :precision="0"
                    v-model="activeWidget.style.top"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                </div>
                <div class="style-config">
                  <span class="label">
                    宽度
                  </span>
                  <el-input-number
                    v-model="activeWidget.style.width"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                  <span class="label">
                    高度
                  </span>
                  <el-input-number
                    v-model="activeWidget.style.height"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                </div>
                <div class="style-config">
                  <template
                    v-if="activeWidget.setDataRange.box.detail.background"
                  >
                    <span class="label">
                      背景色
                    </span>
                    <el-color-picker
                      v-model="activeWidget.style.background"
                      class="w-60"
                      show-alpha
                      size="mini"
                    ></el-color-picker>
                  </template>
                  <span class="label">
                    层级
                  </span>
                  <el-input-number
                    disabled
                    :value="activeWidget.style.zIndex"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                </div>
                <div class="style-config">
                  <!-- <span class="label">
                     对齐
                   </span>
                   {{activeWidget.style.textAlign}}-->
                </div>
              </el-collapse-item>
              <el-collapse-item
                v-if="activeWidget.setDataRange.innerStyle.show"
                title="字体样式"
                name="3"
              >
                <div class="style-config">
                  <span class="label">
                    大小
                  </span>
                  <el-input-number
                    v-model="activeWidget.style.fontSize"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                  <span class="label">
                    行高
                  </span>
                  <el-input-number
                    v-model="activeWidget.style.lineHeight"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                </div>
                <div class="style-config">
                  <span class="label">
                    字距
                  </span>
                  <el-input-number
                    v-model="activeWidget.style.letterSpacing"
                    class="w-60"
                    :controls="false"
                    size="mini"
                  ></el-input-number>
                  <span class="label">
                    颜色
                  </span>
                  <el-color-picker
                    v-model="activeWidget.style.color"
                    class="w-60"
                    show-alpha
                    size="mini"
                  ></el-color-picker>
                </div>
                <div class="style-config">
                  <!--<span class="label">
                    对齐
                  </span>
                  <el-input-number class="w-60" :controls="false" size="mini"></el-input-number>-->
                  <!-- <span class="label">
                     字体
                   </span>
                   <el-input-number class="w-60" :controls="false" size="mini"></el-input-number>-->
                </div>
                <div class="style-config">
                  <span class="label">
                    对齐
                  </span>
                  <align-select
                    v-model="activeWidget.style.align"
                  ></align-select>
                </div>
                <div class="style-config">
                  <span class="label">其他</span>
                  <span
                    :class="{ active: activeWidget.style.isBold }"
                    @click="handleOtherClick('isBold')"
                    class="cursor-p other"
                    ><b>B</b></span
                  >
                  <span
                    :class="{ active: activeWidget.style.isOblique }"
                    @click="handleOtherClick('isOblique')"
                    class="m-l-8 cursor-p other"
                    ><i>I</i></span
                  >
                  <span></span>
                </div>
              </el-collapse-item>
            </el-collapse>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>
<script>
import _ from 'lodash';
import draggable from 'vuedraggable';
import uuid from 'uuid';
import html2canvas from 'html2canvas';
import { Loading } from 'element-ui';
import alignSelect from './alignSelect';
import widget from './widget';
import blankDialog from '@/components/blankDialog';
import imageSelection from '@/components/imageSelection';
import { setDataRangeMap, defaultDataMap } from './widgetInitDataMap';
import Icon from './icon/index';
import { qrUpdate } from '@/api/index';
import VueQr from 'vue-qr';
import { VueCanvasPoster } from 'vue-canvas-poster';

let zIndex = 0;

export default {
  name: 'posterEditor',
  props: {
    order: {
      type: Number,
      required: true
    },
    id: {
      type: String,
      required: true
    },
    value: {
      type: Object,
      required: true
    },
    page: {
      type: Object,
      default() {
        return {
          width: 620,
          height: 375
        };
      }
    }
  },
  components: {
    widget,
    draggable,
    alignSelect,
    blankDialog,
    imageSelection,
    Icon,
    VueQr,
    VueCanvasPoster
  },
  data() {
    return {
      painting: {
        width: '120px',
        height: '120px',
        background: '#eee',
        views: [
          {
            type: 'qrcode',
            content: 'http://golden.shangqie.cn/#/?id=' + this.id,
            css: {
              top: '0',
              left: '0',
              color: '#000',
              width: '120px',
              height: '120px'
            }
          }
        ]
      },
      imgArr: '',
      editorUid: 'uid' + uuid(),
      dZoom: 0.52,
      isDragging: false,
      activeNames: ['1', '2', '3', '4', '5', '6'],
      widgetList: [],
      dragStartPosition: null,
      widgetDragStart: null, // 当前拖的是哪个文本图层 便于后期交互值
      handleResizeFn: null,
      handleActiveWidgetChange: null,
      showImageSelection: false,
      showImageSelectionWidget: false,
      widgetHistory: [], // 记录历史记录变动的
      historyIndex: -1
    };
  },
  methods: {
    resetItme() {
      this.$emit('resetData');
    },
    success(e) {
      this.imgArr = e;
    },
    fail(e) {
      console.log(e);
    },
    submitImg() {
      html2canvas(
        document
          .querySelector(`#${this.editorUid}`)
          .querySelector('.poster-content'),
        {
          useCORS: true,
          // 编辑器缩放保持 960 * 720 的尺寸
          scale: 1 / this.dZoom
        }
      ).then(canvas => {
        localStorage.setItem('itemImg', canvas.toDataURL());
        qrUpdate({
          id: this.id,
          notice: JSON.stringify(this.value),
          noticePic: localStorage.getItem('itemImg')
        }).then(({ message }) => {
          this.msgSuccess(message);
          this.$router.go(-1);
        });
      });
    },
    beforeAddImgWidget(imgObj) {
      this.addWidget('img', imgObj.path);
      this.showImageSelectionWidget = false;
    },
    addWidget(type, path) {
      zIndex++;
      const typeLabelMap = {
        text: '文本',
        img: '图片'
      };
      const item = {
        label: typeLabelMap[type],
        type,
        content: type === 'text' ? '文本' : path,
        uuid: uuid(),
        active: false,
        setDataRange: setDataRangeMap[type],
        style: {
          ...defaultDataMap[type],
          zIndex
        }
      };
      this.widgetList.push(item);
      this.$nextTick(() => {
        this.handleActiveWidget(item);
      });
      this.$emit('input', {
        background: this.value.background,
        widgetList: this.widgetList
      });
      this.pushHistory('add', item, this.widgetList.length - 1);
    },
    handleActiveWidget(item) {
      this.widgetList.forEach(w => {
        if (item.uuid === w.uuid) {
          w.active = !item.active;
        } else {
          w.active = false;
        }
      });
    },
    getOptions() {
      return {
        filter: '.disabled'
      };
    },
    dragStart(e) {
      this.dragStartPosition = {
        pageX: e.pageX,
        pageY: e.pageY
      };
    },
    dragEnd(e, item, index) {
      item.history = {
        content: item.content,
        style: _.cloneDeep(item.style)
      };
      let target = item.style;
      let left = (e.pageX - this.dragStartPosition.pageX) / this.dZoom;
      let top = (e.pageY - this.dragStartPosition.pageY) / this.dZoom;
      target.left = Math.max(
        Math.min(left + target.left, this.page.width - target.width),
        0
      );
      target.top = Math.max(
        Math.min(top + target.top, this.page.height - target.height),
        0
      );
      this.pushHistory('modify', item, index);
    },
    deleteWidget(item) {
      let index = this.widgetList.findIndex(v => v.uuid === item.uuid);
      if (index > -1) {
        this.$confirm(
          `此操作将永久删除该${item.label}图层, 是否继续?`,
          '警告',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }
        ).then(() => {
          this.widgetList.splice(index, 1);
          this.pushHistory('delete', item, index);
        });
      }
    },
    handleOtherClick(key) {
      this.activeWidget.style[key] = !this.activeWidget.style[key];
    },
    dragZIndexStart(item) {
      this.widgetDragStart = item;
    },
    dragZIndexEnd(item) {
      let tmp = item.style.zIndex;
      item.style.zIndex = this.widgetDragStart.style.zIndex;
      this.widgetDragStart.style.zIndex = tmp;
      this.widgetDragStart = null;
    },
    getDZoom() {
      // const currentEditorBox = document.querySelector(`#${this.editorUid}`).getBoundingClientRect()
      // fix v-show隐藏元素宽度太小的问题
      const currentEditorBox = document
        .querySelector(`.poster-editor-comp`)
        .getBoundingClientRect();
      let width = currentEditorBox.width - 32 - 295;
      if (width >= 480) {
        this.dZoom = Number((width / 960).toFixed(2));
      }
      if (width >= 960) {
        this.dZoom = 1;
      }
    },
    // 上传当前poster截图
    uploadCurrentPosterShot(cb) {
      let instance = Loading.service({
        text: '保存中，请稍候！',
        background: 'rgba(0, 0, 0, 0.5)'
      });
      console.time('1');
      this.widgetList.forEach(w => {
        w.active = false;
      });
      let that = this;
      return new Promise(resolve => {
        // 激活当前编辑器 方便截图
        this.$emit('active');
        this.$nextTick(() => {
          html2canvas(
            document
              .querySelector(`#${this.editorUid}`)
              .querySelector('.poster-content'),
            {
              useCORS: true,
              // 编辑器缩放保持 960 * 720 的尺寸
              scale: 1 / this.dZoom
            }
          ).then(async canvas => {
            // console.timeEnd('1');
            // console.time('2');
            localStorage.setItem('itemImg', canvas.toDataURL());
            let file = canvas
              .toDataURL('image/jpeg', 1)
              .replace('data:image/jpeg;base64,', '');
            // console.log('图片');
            // console.log(file);
            // base64的图片
            // console.timeEnd('2');
            // console.time('3');

            const link = document.createElement('a');
            link.href = canvas.toDataURL();
            link.setAttribute('download', new Date().getTime() + '.png');
            link.style.display = 'none';
            document.body.appendChild(link);
            link.click();

            if (cb) {
              await cb(file, resolve);
              // console.timeEnd('3');
              instance.close();
            }
          });
        });
      });
    },
    changeBackground(imgUrl) {
      this.value.background.img = imgUrl;
      // this.value.background = imgUrl;
      // this.value.material_uid = imgObj.uid;
      // this.value.materialType = imgObj.expandType;
      this.showImageSelection = false;
    },
    changeTextColor(color) {
      this.value.background.color = color;
    },
    pushHistory(type, item, index) {
      const obj = {
        uuid: item.uuid,
        item,
        index,
        type
      };
      if (this.canClickNext) {
        // 已经执行过撤销的操作了 再添加历史记录把后面的删除掉
        this.widgetHistory.length = this.historyIndex + 1;
      }
      this.widgetHistory.push(obj);
      this.historyIndex = this.widgetHistory.length - 1;
      /* switch (type) {
        case 'add':
          obj.type = 'add'

          this.historyIndex = this.widgetHistory.length - 1
          break
        case 'delete':
          obj.type = 'delete'
          this.widgetHistory.push(obj)
          this.historyIndex = this.widgetHistory.length
          break
        case 'modify':
          break
      } */
    },
    getHistory(num) {
      if ((num < 0 && this.canClickPrev) || (num > 0 && this.canClickNext)) {
        if (num > 0) this.historyIndex += num;
        let historyObj = this.widgetHistory[this.historyIndex];
        switch (historyObj.type) {
          case 'add':
            // 撤回操作
            if (num < 0) {
              let index = this.widgetList.findIndex(
                v => v.uuid === historyObj.uuid
              );
              if (index > -1) {
                this.widgetList.splice(index, 1);
              }
            } else {
              this.widgetList.push(historyObj.item);
            }
            break;
          case 'delete':
            if (num < 0) {
              this.widgetList.splice(historyObj.index, 0, historyObj.item);
            } else {
              this.widgetList.splice(historyObj.index, 1);
            }
            break;
          case 'modify':
            if (num < 0) {
              this.$set(this.widgetList, historyObj.index, {
                ...historyObj.item,
                style: historyObj.item.history.style,
                content: historyObj.item.history.content
              });
            } else {
              this.$set(this.widgetList, historyObj.index, {
                ...historyObj.item
              });
            }
        }
        if (num < 0) {
          this.historyIndex += num;
        }
        // this.widgetHistory[this.historyIndex - 1]
      }
    }
  },
  computed: {
    activeWidget() {
      return this.widgetList.find(w => w.active);
    },
    sortWidgetList() {
      return this.widgetList
        .slice(0)
        .sort((a, b) => b.style.zIndex - a.style.zIndex);
    },
    canClickPrev() {
      // 是否能点击上一步
      return this.historyIndex > -1;
    },
    canClickNext() {
      return (
        this.historyIndex < this.widgetHistory.length - 1 &&
        this.widgetHistory.length > 0
      );
    }
  },
  watch: {
    widgetList: {
      handler(val) {
        zIndex = val.length;
        val.forEach((v, i) => {
          v.style.zIndex = i + 1;
        });
        this.$emit('input', {
          background: this.value.background,
          widgetList: this.widgetList
        });
      },
      deep: true
    },
    'value.widgetList': {
      handler(val) {
        if (val !== this.widgetList) {
          this.widgetList = val;
        }
      },
      deep: true
    },
    imgArr() {
      // 解决多次合并
      const noticeItem = localStorage.getItem('notice');
      if (noticeItem == 'null') {
        const item = [
          {
            label: '图片',
            type: 'img',
            content: this.imgArr,
            uuid: '32a' + +new Date(),
            active: false,
            style: {
              top: 129,
              left: 86,
              height: 120,
              width: 120,
              align: { x: 0, y: 0 },
              lineHeight: 14,
              fontSize: 14,
              background: 'rgba(0, 0, 0, 0)',
              color: 'rgba(0, 0, 0, 1)',
              letterSpacing: 0,
              isOblique: false,
              isBold: false,
              zIndex: 1
            },
            setDataRange: {
              box: {
                show: true,
                detail: {
                  top: true,
                  left: true,
                  height: true,
                  width: true,
                  background: false,
                  zIndex: true
                }
              },
              content: {
                show: false
              },
              innerStyle: {
                show: false,
                detail: {
                  align: true,
                  lineHeight: true,
                  fontSize: true,
                  color: true,
                  letterSpacing: true,
                  isOblique: true,
                  isBold: true
                }
              }
            }
          },
          {
            label: '文本',
            type: 'text',
            content: '提货须知',
            uuid: '32b' + +new Date(),
            active: false,
            style: {
              top: 108,
              left: 269,
              height: 40,
              width: 120,
              align: { x: 0, y: 0 },
              lineHeight: 14,
              fontSize: 18,
              background: 'rgba(0, 0, 0, 0)',
              color: 'rgba(0, 0, 0, 1)',
              letterSpacing: 0,
              isOblique: false,
              isBold: true,
              zIndex: 1
            },
            setDataRange: {
              box: {
                show: true,
                detail: {
                  top: true,
                  left: true,
                  height: true,
                  width: true,
                  background: false,
                  zIndex: true
                }
              },
              content: {
                show: false
              },
              innerStyle: {
                show: false,
                detail: {
                  align: true,
                  lineHeight: true,
                  fontSize: true,
                  color: true,
                  letterSpacing: true,
                  isOblique: true,
                  isBold: true
                }
              }
            }
          },
          {
            label: '文本',
            type: 'text',
            content: `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 微信或者手机浏览器扫码提货卡二维码，填写姓名、手机号、邮寄地址，点击“我要提货”<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 一个手机号仅限验证一次，提交地址后即可失效<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 有问题请联系客服 0551-63442479`,
            uuid: '32c' + +new Date(),
            active: false,
            style: {
              top: 142,
              left: 268,
              height: 155,
              width: 345,
              align: { x: 0, y: 0 },
              lineHeight: 30,
              fontSize: 16,
              background: 'rgba(0, 0, 0, 0)',
              color: 'rgba(0, 0, 0, 1)',
              letterSpacing: 0,
              isOblique: false,
              isBold: false,
              zIndex: 1
            },
            setDataRange: {
              box: {
                show: true,
                detail: {
                  top: true,
                  left: true,
                  height: true,
                  width: true,
                  background: false,
                  zIndex: true
                }
              },
              content: {
                show: false
              },
              innerStyle: {
                show: false,
                detail: {
                  align: true,
                  lineHeight: true,
                  fontSize: true,
                  color: true,
                  letterSpacing: true,
                  isOblique: true,
                  isBold: false
                }
              }
            }
          }
        ];
        this.value.widgetList = [...this.value.widgetList, ...item];
      } else {
      }
    }
  },
  mounted() {
    this.getDZoom();
    this.handleResizeFn = _.throttle(this.getDZoom, 100);
    window.addEventListener('resize', this.handleResizeFn);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResizeFn);
  },
  created() {
    console.log(this.value);
    this.widgetList = this.value.widgetList || [];
    this.widgetList.forEach(v => {
      v.history = {
        content: v.content,
        style: _.cloneDeep(v.style)
      };
    });
  }
};
</script>
<style lang="scss" scoped>
.w-60 {
  width: 60px !important;
}
.poster-editor-comp {
  display: flex;
  min-width: 830px;
  .main-pane {
    background-color: #7f7f7f;
    position: relative;
    flex: 1;
    padding: 0 16px;
    .header-ct {
      display: flex;
      height: 40px;
      align-items: center;
      text-align: center;
      .left {
        display: flex;
        align-items: center;
        .mirror {
          transform: rotateY(180deg);
        }
      }
      .center {
        color: #fff;
        flex: 1;
      }
    }
    .poster-content {
      border: 1px solid #ccc;
      top: 100px;
      left: 50%;
      position: absolute;
      /*min-width: 480px;
      min-height: 360px;
      max-width: 960px;
      max-height: 720px;*/
      width: 960px;
      height: 720px;
      /* margin: 0 auto;*/
      transform: translateX(-50%);
      &:hover {
        outline: 1px solid grey;
      }
      transform-origin: 0 0;
      background-size: 100% 100% !important;
      .bg-puppet {
        width: 100%;
        height: 100%;
        z-index: -1;
      }
    }
  }
  .right-pane {
    box-sizing: border-box;
    width: 295px;
    padding-left: 16px;
    border: 1px solid #e4e4e4;
    background: #fff;
    z-index: 900;
    .header-ct {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      height: 40px;
    }
    .style-setting-ct {
      .style-config {
        display: flex;
        align-items: center;
        margin-bottom: 8px;
        padding-left: 16px;
        .label {
          display: inline-block;
          margin-left: 8px;
          width: 48px;
          text-align: left;
        }
        .other {
          width: 20px;
          height: 20px;
          line-height: 20px;
          text-align: center;
          font-size: 18px;
          color: rgba(0, 0, 0, 0.8);
          &.active {
            background: rgba(0, 0, 0, 0.8);
            color: white;
          }
        }
      }
    }
    .widget-zIndex-config-ct {
      .widget-list-item {
        cursor: move;
      }
      .item {
        position: relative;
        display: flex;
        align-items: center;
        height: 40px;
        border-bottom: 1px solid #e1e1e1;
        font-size: 14px;
        .delete-btn {
          position: absolute;
          display: none;
          transition: all 200ms linear;
        }
        &:hover .delete-btn {
          display: block;
        }
        .view {
          margin-left: 40px;
          width: 24px;
          height: 18px;
          background-size: 100% 100% !important;
          border: 1px solid rgba(0, 0, 0, 0.3);
        }
        .desc {
          font-size: 14px;
        }
      }
      .bg {
        .view {
          margin-left: 24px;
        }
      }
    }
  }
}
</style>
