<template>
  <div class="template">
    <word-item
      v-for="(item, index) in words"
      :word="item"
      :word-index="index"
      @show-action-handler="showActionHandler"
      :key="index"
      @pre-add-word="preAddWord"
      class="template-item van-hairline--top"
    ></word-item>
    <div class="add-word" @click="preAddWord({ wordType: DataType.Unit })">
      <common-svg name="tianjia" style="margin-right:10px;"></common-svg
      >添加一级标题
    </div>
    <p class="tip">比如：基本信息、出厂信息、图片描述……</p>
    <div class="btn-group">
      <div
        role="button"
        v-show="words.length > 0"
        class="preview"
        @click="$emit('show-preview')"
      >
        预览
      </div>
      <div
        role="button"
        class="slc-btn-common confirm"
        @click="$emit('confirm-words')"
      >
        确定
      </div>
    </div>
    <van-dialog
      v-model="show"
      :before-close="addWord"
      :title="levelObj.title"
      show-cancel-button
    >
      <van-field
        v-model="wordName"
        label=""
        :placeholder="levelObj.placeholder"
      />
      <div
        v-if="wordType !== DataType.Unit && flag !== FLAG_UPDATE"
        @click="handleClickFieldType"
        style="text-align:left;display:flex;justify-content:space-between;padding:16px;color:#999999;font-size:14px;"
      >
        <span>字段类型</span> <span>{{ typeObj[wordType] }}</span>
      </div>
    </van-dialog>
    <add-option
      :showOptions.sync="showOptions"
      :dataType.sync="activeName"
      :radioBoxOptions.sync="options"
      @back="showOptions = false"
      @confirmWordType="confirmWordType"
    ></add-option>
    <more-action
      :show.sync="showMoreAction"
      :menuList="menuList"
      @cb="callbackFromMoreAction"
    ></more-action>
  </div>
</template>
<script lang="ts">
import { Component, Prop, PropSync, Vue } from 'vue-property-decorator';
import {
  List,
  Image,
  Field,
  Dialog,
  GridItem,
  Grid,
  Button,
  Popup,
} from 'vant';
import { TEMPLATETYPE, DataType } from '@/const/enum';
import WordItem from './WordItem.vue';
import AddOption from './AddOption.vue';
import { IData, TemplateDataItem } from '@/const/interface';

const FLAG_UPDATE = 'update';
const FLAG_BEFORE = 'before';
const FLAG_AFTER = 'after';

@Component({
  components: {
    WordItem,
    AddOption,
  },
})
export default class Add extends Vue {
  @PropSync('data', {
    required: true,
    type: Array,
  })
  private words!: any[];
  private wordType: DataType = DataType.Unit;
  private readonly DataType: any = DataType;
  private wordName: string = '';

  private flag: string = '';
  private FLAG_UPDATE = FLAG_UPDATE;
  private isModifyForm = false;

  private options: string[] = [];
  private activeName = 0;
  private addOptionPropOption = [] as string[];
  private currentWords: any[] = [];

  private showOptions: boolean = false;
  private show: boolean = false;

  private showMoreAction: boolean = false;
  private currentAction: { index: number; parentIndex: number } = {
    index: -1,
    parentIndex: -1,
  };

  get menuList() {
    const list = [
      {
        icon: 'zaishangtianjia2x',
        text: '在上添加',
        callback: this.addBefore.bind(this),
      },
      {
        icon: 'zaixiatianjia2x',
        text: '在下添加',
        callback: this.addAfter.bind(this),
      },
      {
        icon: 'shanchu2x',
        text: '删除',
        callback: this.delWord.bind(this),
      },
      {
        icon: 'zhongmingming2x',
        text: '重命名',
        callback: this.rename.bind(this),
      },
      {
        isField: true,
        icon: 'xiugaibianxianxingshi2x',
        text: '修改表现形式',
        callback: this.modifyForm.bind(this),
      },
    ];
    return list.filter((item: any) => {
      if (this.currentAction.parentIndex === -1) {
        // 如果是标题
        return !item.isField;
      } else {
        // 如果是字段
        return true;
      }
    });
  }

  private readonly typeObj: any = {
    [DataType.Input]: '单行文本',
    [DataType.Image]: '图片',
    [DataType.File]: 'pdf文件',
    [DataType.Unit]: '一级标题',
    [DataType.Select]: '选择',
    [DataType.Date]: '日期',
    [DataType.Video]: '视频',
    [DataType.Audio]: '音频',
    [DataType.TextArea]: '多行文本',
  };
  private typeValue: any = {
    0: {
      data: {
        type: 'text',
        format: 'string',
        value: '',
      },
      type: 0,
      key: '',
      label: '单行文本',
    },
    1: {
      data: {
        type: 'image',
        format: 'hash',
        value: [],
      },
      type: 1,
      key: '',
      label: '图片',
    },
    2: {
      data: {
        type: 'file',
        format: 'hash',
        value: [],
      },
      type: 2,
      key: '',
      label: 'pdf',
    },
    3: {
      data: [],
      type: 3,
      key: '',
      label: '一级标题',
    },
    5: {
      data: {
        type: 'text',
        format: 'string',
        value: '',
      },
      type: 5,
      key: '',
      options: [],
      label: '选择',
    },
    6: {
      data: {
        type: 'date',
        format: 'utc',
        value: 0,
      },
      type: 6,
      key: '',
      label: '日期',
    },
    8: {
      data: {
        type: 'video',
        format: 'hash',
        value: [],
      },
      type: 8,
      key: '',
      label: '视频',
    },
    9: {
      data: {
        type: 'audio',
        format: 'hash',
        value: [],
      },
      type: 9,
      key: '',
      label: '音频',
    },
    10: {
      data: {
        type: 'text',
        format: 'string',
        value: '',
      },
      type: 10,
      key: '',
      label: '多行文本',
    },
  };
  private showActionHandler({ index, parentIndex }: any) {
    this.showMoreAction = true;
    this.currentAction = { index, parentIndex };
  }

  private resolveAction(flag: string = '') {
    const { index, parentIndex } = this.currentAction;
    const wordType = parentIndex === -1 ? DataType.Unit : DataType.Input;
    const word = parentIndex !== -1 ? this.words[parentIndex] : null;
    this.preAddWord({ wordType, word }, flag);
  }
  private addBefore() {
    this.resolveAction(FLAG_BEFORE);
  }
  private addAfter() {
    this.resolveAction(FLAG_AFTER);
  }
  private rename() {
    this.resolveAction(FLAG_UPDATE);
  }
  private async delWord() {
    const { index, parentIndex } = this.currentAction;
    const tempWords =
      parentIndex === -1 ? this.words : this.words[parentIndex].data;
    if (parentIndex === -1 && this.words[index].data.length > 0) {
      await this.$dialog.confirm({
        title: '提示',
        message: '该内容下包含多条字段，确定要删除吗',
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      });
    }
    return tempWords.splice(index, 1);
  }

  // 返回当前选中的项
  private getFocusedItem(parentIndex: number, index: number) {
    if (parentIndex === -1) {
      // 当前点击的是标题
      return this.words[index];
    } else {
      // 当前点击的是字段
      return this.words[parentIndex].data[index];
    }
  }

  // 修改表现形式
  private modifyForm() {
    this.isModifyForm = true;
    const clickedField = this.getFocusedItem(
      this.currentAction.parentIndex,
      this.currentAction.index
    );
    this.activeName = clickedField.type;
    this.addOptionPropOption = clickedField.options ? clickedField.options : [];
    this.showOptions = true;
  }

  private handleClickFieldType() {
    if (this.flag === FLAG_UPDATE) {
      this.activeName = this.wordType;
      this.addOptionPropOption = this.options;
    } else {
      this.activeName = this.wordType;
      this.addOptionPropOption = [];
    }
    this.showOptions = true;
  }

  private callbackFromMoreAction(action: any) {
    action();
  }

  private confirmWordType({ type = DataType.Input, options }: any) {
    // 若是由直接修改表现形式而弹出add-options组件，确认完表现形式后，是直接修改当前项的值。
    if (this.isModifyForm) {
      const currentItem = this.getFocusedItem(
        this.currentAction.parentIndex,
        this.currentAction.index
      );
      currentItem.type = type;
      currentItem.options = options;
    } else {
      // 如果不是修改表现形式，则是由对话框中点击字段类型而弹出add-options组件，若确认完表现形式，则是修改对话框中字段类型的值。
      this.wordType = type;
      this.options = options;
    }
    this.showOptions = false;
  }
  get levelObj(): any {
    if (this.wordType === DataType.Unit) {
      return {
        title: this.flag === FLAG_UPDATE ? '更新标题' : '添加标题',
        placeholder: '一级标题名称',
        toast: '标题至少2个汉字',
      };
    }
    return {
      title: this.flag === FLAG_UPDATE ? '更新字段' : '添加字段',
      placeholder: '字段名称',
      toast: '字段至少2个汉字',
    };
  }

  private preAddWord({ wordType, word }: any, flag: string = '') {
    this.show = true;
    this.wordType = wordType;
    this.currentWords = word ? word.data : this.words;
    if (flag === FLAG_UPDATE) {
      const { index, parentIndex } = this.currentAction;
      const currentWord =
        parentIndex === -1
          ? this.words[index]
          : this.words[parentIndex].data[index];
      this.wordName = currentWord.label;
      this.wordType = currentWord.type;
    }
    this.flag = flag;
  }

  private deepClone(data: any) {
    return JSON.parse(JSON.stringify(data));
  }
  private addWord(action: string, done: any) {
    if (action !== 'confirm') {
      return done();
    }
    if (this.wordName === '') {
      this.$toast(this.levelObj.toast);
      return done(false);
    }
    let tempData = {
      ...this.deepClone((this.typeValue as any)[this.wordType]),
      label: this.wordName,
    };
    if (this.wordType === DataType.Select) {
      tempData = { ...tempData, options: this.options };
    }
    let { index } = this.currentAction;
    if (this.flag === FLAG_UPDATE) {
      this.currentWords.splice(index, 1, tempData);
    } else if (this.flag === FLAG_BEFORE) {
      this.currentWords.splice(index, 0, tempData);
    } else if (this.flag === FLAG_AFTER) {
      this.currentWords.splice(++index, 0, tempData);
    } else {
      this.currentWords.push(tempData);
    }
    this.wordName = '';
    this.wordType = DataType.Unit;
    this.flag = '';
    done();
  }
}
</script>
<style scoped lang="scss">
.template-item {
  text-align: left;
  display: flex;
  flex-direction: column;
  font-size: 10px;
  line-height: 1.5;
  color: #818181;
  background: #ffffff;
  padding: 0 17px;
  margin-bottom: 20px;
}
.add-word {
  padding: 17px;
  margin: 0 20px;
  margin-top: 20px;
  font-size: 16px;
  color: #3f79fe;
  border-radius: 6px;
  border: 1px dashed rgba(63, 121, 254, 1);
}
.tip {
  font-size: 12px;
  color: #737582;
  margin-bottom: 100px;
}
.btn-group {
  .preview {
    align-self: center;
    color: #353535;
    background: #f0f1f5;
    border-radius: 4px;
    width: 107px;
    padding: 9px;
    margin-right: 10px;
  }
  .confirm {
    flex: auto;
    align-self: center;
    width: 228px;
    padding: 9px;
  }
}
</style>
