<template>
  <el-form-item :label="showLabel ? label : ''" :rules="[...requireRule(required, label, type), ...rules]" :prop="prop"
    :labelWidth="labelWidth">
    <template #label>
      <el-tooltip :content="label" placement="top" :disabled="isShowTooltip">
        <span @mouseenter="visibleTooltip">{{ label }}</span>
      </el-tooltip>
    </template>
    <el-tooltip v-if="showTip && !isBlank(formRef.model[prop])" placement="top">
      <div slot="content">{{ initName }}</div>
      <el-input ref="inputs" v-model="formRef.model[prop]" :style="{ width }"
        :placeholder="!disabled && (placeholder || $t('common.pleaseInputHasPara', [label]))"
        @blur="formRef.model[prop] = $event.target.value.trim()" @input="$forceUpdate()" :clearable="clearable"
        @clear="clear" :disabled="disabled || showFormula" :type="type" :rows="rows" @focus="focus" show-word-limit
        :trigger="trigger" :readonly="readonly" :maxlength="maxlength" class="custom-input"
        @change="$emit('change', formRef.model[prop])">
      </el-input>
    </el-tooltip>
    <el-input v-if="!showTip || isBlank(formRef.model[prop])" ref="inputs" v-model="formRef.model[prop]"
      :style="{ width }" :placeholder="!disabled && (placeholder || $t('common.pleaseInputHasPara', [label]))"
      @blur="formRef.model[prop] = $event.target.value.trim()" @input="$forceUpdate()" :clearable="clearable"
      @clear="clear" :disabled="disabled || showFormula" :type="type" :rows="rows" @focus="focus" show-word-limit
      :trigger="trigger" :readonly="readonly" :maxlength="maxlength"
      :class="{ 'custom-input': true, 'formula-input': showFormula }" @change="$emit('change', formRef.model[prop])">
      <template #append v-if="showButton || showFormula">
        <el-button :type="buttonType" @click="() => $emit('buttonClick')" v-if="showButton">{{ buttonLabel
          }}</el-button>
        <el-button :type="buttonType" @click="handleEditFormula" v-if="showFormula" icon="el-icon-edit"></el-button>
      </template>
    </el-input>
    <!-- <span v-else class="content">{{ formRef.model[prop] }}</span> -->

    <el-drawer ref="rowComputedSetting" :visible.sync="rowComputedSettingShow" v-if="showFormula" size="60%"
      :wrapperClosable="false" :modal="false">
      <CustomCard :show-header="false" style="margin-top: 1%">
        <Row>
          <Col>
          <div class="picker">
            <Row style="width: 100%">
              <Col>
              <el-tabs @tab-click="handleTabClick">
                <el-tab-pane v-for="(item, index) in paramsTypeList" :key="index" :label="initTypeNames(item)">
                  <Row style="margin-bottom: 1%" :gutter="20">
                    <Col v-for="(commonParam) in commonParamsList" :span="8" class="paramButton" v-if="index === 0">
                    <el-button icon="el-icon-menu" @click="insertContent(commonParam.paramName, 'variable')"
                      :disabled="type === 4">
                      <span style="color: #5DAAFD">{{ commonParam.paramName }}</span>
                    </el-button>
                    </Col>

                    <Col v-for="(paramType, paramIndex) in paramsGroupByTypeList" :span="8" class="paramButton"
                      v-if="item !== '2' && item !== '1' && item !== '3'">
                    <el-button icon="el-icon-menu" @click="insertContent(paramType.name, 'variable')"
                      :disabled="type === 4">
                      <span style="color: #5DAAFD">{{ paramType.name }}</span>
                    </el-button>
                    </Col>
                    <Col v-for="(funcType, funcIndex) in funList" :span="6" class="paramButton" v-if="item === '2'">
                    <el-button icon="el-icon-menu" @click="insertContent(funcType.name, 'func')" :disabled="type === 4">
                      <span style="color: #5DAAFD">{{ funcType.name }}</span>
                    </el-button>
                    </Col>
                    <Col v-for="(logicType, logicIndex) in logicOperation" :span="6" class="paramButton"
                      v-if="item === '2'">
                    <el-button icon="el-icon-menu" @click="insertContent(logicType.name, 'logic')"
                      :disabled="type === 4">
                      <span style="color: #5DAAFD">{{ logicType.name }}</span>
                    </el-button>
                    </Col>
                    <Col v-for="(optionPara, logicIndex) in optionParaSelection" :span="6" class="paramButton"
                      v-if="item === '3'">
                    <el-button icon="el-icon-menu" @click="insertContent(optionPara.markupName, 'option')"
                      :disabled="type === 4">
                      <span style="color: #5DAAFD">{{ optionPara.markupName }}</span>
                    </el-button>
                    </Col>

                  </Row>
                </el-tab-pane>

              </el-tabs>
              </Col>

            </Row>
          </div>
          </Col>
        </Row>
      </CustomCard>

      <CustomCard :show-header="false" style="margin-top: 1%;" cardHeight="425px">
        <div class="code-edit" style="height: 100%">
          <ButtonTitle :label="$t('validation.formulaSetting')"
            :customStyle="{ background: '#F9FBFD', padding: '0 15px 0 15px', width: '100%', margin: '0 !important' }">
            <CustomButton label="validation.test" type="primary" @handleClick="getContent" />
          </ButtonTitle>

          <CodeEdit ref="codeEditor" v-model="formulaStr" :options="cmOptions" @input="codeMirrorChange"></CodeEdit>
        </div>
      </CustomCard>

      <Row style="position: fixed;bottom: 1%;right: 1%;">
        <Col>
        <CustomButton icon="el-icon-circle-check" type="primary" label="common.confirm" @handleClick="drawerConfirm" />
        <CustomButton icon="el-icon-remove-outline" label="common.cancel" @handleClick="drawerCancel" />
        </Col>
      </Row>
    </el-drawer>

    <Dialog ref="testResult" :title="$t('validation.testresult')" @close="closeCheck" :modal="false" maxWidth="1300px">
      <CustomForm ref="testResultForm" :value="testFormula"  class="testResultForm" labelWidth="120px">
        <CustomInput :span="12" v-for="(item, index) in usedParamsList" :label="`${item.name}`" showTooltip
          :prop="`$_$${item.value}$_$`" :key="index" />
        <el-form-item :label="$t('validation.testresult')">
          <span>{{ testResult }}</span>
        </el-form-item>
      </CustomForm>

      <template #footer>
        <el-row style="text-align: end">
          <CustomButton icon="el-icon-circle-check" type="primary" :label="$t('common.confirm')"
            @handleClick="submitCheckFunction" />
          <CustomButton icon="el-icon-remove-outline" :label="$t('common.cancel')"
            @handleClick="$refs.testResult.close()" />
        </el-row>

      </template>
    </Dialog>
  </el-form-item>
</template>

<script>
import mixin from "./mixin";
import { isBlank } from "../../../../utils";
import { getCommonParamList, testFormulaValidation } from "@/api/business/crm/paraValidation/paraValidation";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/idea.css";
import { codemirror as CodeEdit } from "vue-codemirror";
import { getCommmonPara } from "@/api/business/crm/parabar/parabar";
import { mapGetters } from "vuex";

import { analysisFormula, funList, initReplaceCodeList, logicOperation, getContent, testSubmitCheckFunction } from "@/utils/formula";
/**
 * 输入框组件
 */
export default {
  mixins: [mixin],
  props: {
    type: {
      type: String,
      default: "input",
    },
    maxlength: {
      type: Number | String,
      default: 30,
    },
    rows: {
      type: Number,
      default: 3,
    },
    trigger: {
      type: String,
      default: 'blur'
    },
    labelWidth: {
      type: String
    },
    defaultValue: {
      type: String,
      default: null
    },
    width: {
      type: String,
      default: '640px'
    },
    span: {
      type: Number,
      default: 8
    },
    buttonLabel: {
      type: String,
      default: ''
    },
    buttonType: {
      type: String,
      default: 'primary'
    },
    showButton: {
      type: Boolean,
      default: false
    },
    showTip: {
      type: Boolean,
      default: false
    },
    showFormula: {
      type: Boolean,
      default: false
    },
    elevatorModelIdList: {
      type: Array,
      default: () => []
    },
    optionParaSelection: {
      type: Array,
      default: () => []
    },
  },
  components: {
    CodeEdit,

  },
  data() {
    return {
      paramsTypeList: [],
      commonParamsList: [],
      paramsGroupByTypeList: [],
      cmOptions: {
        // 语言及语法模式
        mode: 'text/javascript',
        // 主题
        theme: "idea",
        // 显示函数
        line: true,
        lineNumbers: false,
        // 软换行
        lineWrapping: true,
        // tab宽度
        tabSize: 4,
      },
      lang: 'javascript',
      formulaStr: "",
      formulaValueStr: "",
      testResult: "",
      formulaSettingForm: {},
      rowComputedSettingShow: false,
      funList,
      logicOperation,
      testFormula: {},
      usedParamsList: [],
      isShowTooltip: false,
    }
  },
  computed: {
    ...mapGetters(["dict"]),
    initName() {
      return this.formRef.model[this.prop];
    },
    editor() {
      return this.$refs.codeEditor?.codemirror;
    },
  },
  created() {

    if (this.showFormula) {
      getCommonParamList().then(res => {
        this.commonParamsList = res.data;
      })
      this.getCommonParams([])
    }

  },
  methods: {
    isBlank,
    focus() {
      this.$emit("focus");
    },
    doFocus() {
      this.$refs.inputs.focus();
    },
    clear() {
      this.$emit("clear")
    },
    visibleTooltip(e) {
      this.isShowTooltip = e.target.offsetWidth + 18 - e.fromElement.clientWidth > 0 ? false : true;  //18为required *号引起的偏差。
    },
    initTypeNames(val) {
      if (typeof val === 'string') {
        let search = this.dict['para_category'].find(item => {
          return item.value == val
        });
        if (search) {
          return search.label;
        } else if (val === '1') {
          return this.$t('validation.commonParameters')
        } else if (val === '3') {
          return this.$t('其他加价项')
        } else {
          return this.$t('validation.Logical')
        }
      }
    },
    handleTabClick(val) {
      if (val.index === '0') {
      } else if (val.index === this.paramsTypeList.length - 1) {
      } else {
        let search = this.dict['para_category'].find(item => item.label === val.label);
        if (search) {
          this.activeParamType = search.value;
          this.paramsGroupByTypeList = this.paramsList.filter(item => item.type === this.activeParamType);
        }
      }
    },
    /**
     * editor 中的对内容进行处理
     * @param label
     * @param type variable | func，variable为表单变量，需标记，func 为函数，也需要做标记
     */
    insertContent(label, type) {
      const from = this.editor.getCursor();
      if (type === 'variable') {
        this.editor.replaceSelection(label);
        const to = this.editor.getCursor();
        this.markText(from, to, label, 'cm-field');
      } else if (type === 'func') {
        this.editor.replaceSelection(`${label}()`);
        const to = this.editor.getCursor();
        this.markText(from, { line: to.line, ch: to.ch - 2 }, label, 'cm-func');
        this.editor.setCursor({ line: to.line, ch: to.ch - 1 });
      } else if (type === 'funcInit') {
        this.editor.replaceSelection(`${label}`);
        const to = this.editor.getCursor();
        this.markText(from, { line: to.line, ch: to.ch }, label, 'cm-func');
      } else if (type === 'logic') {
        this.editor.replaceSelection(label);
        const to = this.editor.getCursor();
        this.markText(from, to, label, 'cm-logic');
      } else if (type === 'option') {
        this.editor.replaceSelection(label);
        const to = this.editor.getCursor();
        this.markText(from, to, label, 'cm-field');
      } else if (typeof label === 'string') {
        this.editor.replaceSelection(label);
      }
      this.editor.focus();
    },
    handleEditFormula() {
      // 激活弹框
      this.rowComputedSettingShow = true;
      this.formulaStr = this.formRef.model[this.prop];
      this.formulaValueStr = this.formulaStr;
    },
    drawerConfirm() {
      if (isBlank(this.formulaStr)) {
        this.$message.error("请输入公式");
        return;
      }
      this.formRef.model[this.prop] = this.formulaStr;
      this.$emit("change", this.formulaStr);
      this.rowComputedSettingShow = false;
    },
    drawerCancel() {
      this.rowComputedSettingShow = false;
      this.formulaStr = "";
      this.formulaValueStr = "";
    },
    codeMirrorChange() {
      //获取 editor 的内容
      this.formulaValueStr = this.formulaStr;
    },
    sortByKey(array, key) {
      return array.sort(function (a, b) {
        var x = !isBlank(key) ? a[key] : a;
        var y = !isBlank(key) ? b[key] : b;
        return ((x > y) ? -1 : ((x < y) ? 1 : 0));
      });
    },
    getContent() {
      getContent(this)
    },
    getParam(str) {
      let matchList = [];
      const regex = /(\$_\$.*?\$_\$)/g;
      const matches = str.match(regex);
      if (matches) {
        matches.forEach(match => {
          matchList.push(match)
        });
      }
      return matchList;
    },
    getCommonParams() {
      let value = this.elevatorModelIdList;
      let param = {
        language: this.$i18n.locale,
        relatedModel: value,
        modelCount: value.length,
      }
      getCommmonPara(param).then(res => {
        if (res) {
          this.paramsList = res.map(item => {
            return {
              name: item.paraName,
              value: item.paraCode,
              type: item.paraCategory,
              inputType: item.inputType,
              key: item.paraId
            };
          });
          this.paramsTypeList = this.paramsList.map(item => item.type);
          let map = new Set(this.paramsTypeList);
          this.paramsTypeList = Array.from(map);
          this.paramsTypeList = ['1',
            ...this.paramsTypeList,
            '2'
          ]
          if (this.optionParaSelection.length > 0) {
            this.paramsTypeList.push('3')
          }
        }
      })
    },
    markText(from, to, label, className) {
      if (className === void 0) {
        className = "cm-func";
      }
      let text = document.createElement("span");
      text.className = className;
      text.innerText = label;
      this.editor.markText(from, to, {
        atomic: true,
        replacedWith: text,
      });
    },
    closeCheck() {
      this.testFormula = {};
      this.testResult = null;
    },
    async submitCheckFunction() {
      this.formulaValueStr = this.formulaStr
      return testSubmitCheckFunction(this, this.formulaValueStr, this.paramsList, this.testFormula, this.usedParamsList)
    },
  },

  mounted() {
    if (this.defaultValue != null && this.defaultValue != '' &&
      (this.formRef.model[this.prop] == null || this.formRef.model[this.prop] == '' || this.formRef.model[this.prop] == undefined)) {
      this.formRef.model[this.prop] = this.defaultValue
    }
  }
};
</script>

<style>
.detail-form .formula-input .el-input__inner:not(.pagination) {
  width: 180px !important;
}

.custom-input.el-input__inner {
  width: 495px !important;
}
</style>
<style scoped>
.custom-input.el-textarea {
  width: 495px
}

.content {
  padding: 5px 10px;
  border-bottom: 1px solid;
  width: 100%;
  display: block;
  min-height: 46px;
}

/deep/ .el-form-item__label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /*display:inline;*/
}

/deep/ .CodeMirror {
  height: 200px !important;
  /*表单变量样式*/

  .cm-field {
    background: #007bff;
    padding: 3px 5px;
    border-radius: 3px;
    color: #fff;
    margin: 0 1px;
  }

  /*函数样式*/

  .cm-func {
    font-weight: bold;
    color: #ae4597;
    line-height: 14px;
    margin: 0 1px;
    padding: 0 2px;
  }

  .cm-logic {
    font-weight: bold;
    color: #00afff;
    line-height: 14px;
    margin: 0 1px;
    padding: 0 2px;
  }

  .CodeMirror-scroll {
    height: 200px !important;
  }
}
/deep/ .paramButton{
  padding-bottom: 3px !important;
}
/deep/ .testResultForm .el-form-item__label{
  padding: 0 !important;
  line-height: 1em !important;
}
/deep/ .testResultForm .el-form-item__label{
  padding-left: 10px !important;
}
</style>
