<template>
  <div class="json-build-page page-padding">
    <a-steps :current="active" class="mb-12">
      <a-step
        :title="`${$t('STEP')} 1`"
        :description="$t('BUILD_CONTENT').replace('{}', ' reader')"
      />
      <a-step
        :title="`${$t('STEP')} 2`"
        :description="$t('BUILD_CONTENT').replace('{}', ' writer')"
      />
      <a-step :title="`${$t('STEP')} 3`" :description="$t('FIELD_MAP')" />
      <a-step :title="`${$t('STEP')} 4`" :description="$t('BUILD')" />
    </a-steps>
    <a-button :disabled="active <= 1" @click="handlePrev('add')">
      <span>{{ $t("PREV_STEP") }}</span>
    </a-button>
    <a-button :disabled="active >= 4" @click="handleNext('add')">
      <span>{{ $t("NEXT_STEP") }}</span>
    </a-button>

    <a-form-model
      v-show="active === 1"
      ref="stepOneForm"
      :model="stepOneForm"
      :rules="stepOneRules"
      label-position="left"
      label-width="88px"
      style="margin: 20px 30px"
    >
      <a-form-model-item
        :label="$t('DATA_SOURCE')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="dataSource"
      >
        <a-select
          v-model="stepOneForm.dataSource"
          filterable
          allow-clear
          :placeholder="$t('PLACESELECT')"
          @change="dataSourceChange($event, 'stepOne')"
        >
          <a-select-option
            v-for="item in dataSourceOptions"
            :key="item.id"
            :value="item.id"
          >
            {{ item.dataSourceName }}
          </a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item
        :label="$t('JSON_BUILD_TABLE')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="table"
      >
        <a-select
          v-model="stepOneForm.table"
          filterable
          allow-clear
          show-search
          :placeholder="$t('PLACESELECT')"
          @change="tableChange($event, 'stepOne')"
        >
          <a-select-option
            v-for="(item, index) in stepOne.tableOptions"
            :key="index"
            :value="item"
          >
            {{ item }}
          </a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item
        label="preSql"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="preSql"
      >
        <a-input
          v-model="stepOneForm.preSql"
          style="width: 100%"
          type="textarea"
          :rows="3"
          placeholder="preSql"
          allow-clear
        />
      </a-form-model-item>
      <a-form-model-item
        label="querySql"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 12 }"
        prop="querySql"
      >
        <a-input
          v-model="stepOneForm.querySql"
          style="width: 83.5%"
          type="textarea"
          :rows="3"
          :placeholder="$t('QUERY_SQL_PLACEHOLDER')"
          allow-clear
          @focus="querySqlFocus('stepOne')"
          @blur="querySqlBlur('stepOne')"
        />
        <a-button class="ml-6" @click="handleParseField">
          <span>{{ $t("ANALYSIS_FIELD") }}</span>
        </a-button>
      </a-form-model-item>
      <a-form-model-item
        :label="$t('FIELD')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 22 }"
        prop="fields"
      >
        <a-checkbox
          :indeterminate="stepOne.isIndeterminate"
          :checked="stepOne.checkAll"
          @change="handleCheckAllChange($event, 'stepOne')"
        >
          {{ $t("ALL_SELECT") }}
        </a-checkbox>
        <a-checkbox-group
          v-model="stepOneForm.fields"
          :options="stepOne.fieldOptions"
          @change="handleCheckedChange($event, 'stepOne')"
        />
      </a-form-model-item>
      <a-form-model-item
        label="postSql"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="postSql"
      >
        <a-input
          v-model="stepOneForm.postSql"
          style="width: 100%"
          type="textarea"
          :rows="3"
          placeholder="postSql"
          allow-clear
        />
      </a-form-model-item>
      <a-form-model-item
        label="where"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="where"
      >
        <a-input
          v-model="stepOneForm.where"
          style="width: 100%"
          type="textarea"
          :rows="2"
          :placeholder="`where${$t('CONDITION')}`"
          allow-clear
        />
      </a-form-model-item>
    </a-form-model>

    <a-form-model
      v-show="active === 2"
      ref="stepTwoForm"
      :model="stepTwoForm"
      :rules="stepTwoRules"
      label-position="left"
      label-width="88px"
      style="margin: 20px 30px"
    >
      <a-form-model-item
        :label="$t('DATA_SOURCE')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="dataSource"
      >
        <a-select
          v-model="stepTwoForm.dataSource"
          filterable
          allow-clear
          show-search
          :placeholder="$t('PLACESELECT')"
          @change="dataSourceChange($event, 'stepTwo')"
        >
          <a-select-option
            v-for="item in dataSourceOptions"
            :key="item.id"
            :value="item.id"
          >
            {{ item.dataSourceName }}
          </a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item
        :label="$t('JSON_BUILD_TABLE')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="table"
      >
        <a-select
          v-model="stepTwoForm.table"
          filterable
          allow-clear
          show-search
          :placeholder="$t('PLACESELECT')"
          @change="tableChange($event, 'stepTwo')"
        >
          <a-select-option
            v-for="item in stepTwo.tableOptions"
            :key="item"
            :value="item"
          >
            {{ item }}
          </a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item
        :label="$t('FIELD')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="fields"
      >
        <a-checkbox
          :indeterminate="stepTwo.isIndeterminate"
          :checked="stepTwo.checkAll"
          @change="handleCheckAllChange($event, 'stepTwo')"
        >
          {{ $t("ALL_SELECT") }}
        </a-checkbox>
        <a-checkbox-group
          v-model="stepTwoForm.fields"
          :options="stepTwo.fieldOptions"
          @change="handleCheckedChange($event, 'stepTwo')"
        />
      </a-form-model-item>
      <a-form-model-item
        label="preSql"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="preSql"
      >
        <a-input
          v-model="stepTwoForm.preSql"
          style="width: 42%"
          type="textarea"
          :rows="3"
          placeholder="preSql"
          allow-clear
        />
      </a-form-model-item>
      <a-form-model-item
        label="postSql"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="postSql"
      >
        <a-input
          v-model="stepTwoForm.postSql"
          style="width: 42%"
          type="textarea"
          :rows="3"
          placeholder="postSql"
          allow-clear
        />
      </a-form-model-item>
    </a-form-model>

    <a-form-model
      v-show="active === 3"
      ref="stepThreeForm"
      :model="stepThreeForm"
      :rules="stepThreeRules"
      label-position="left"
      label-width="88px"
      style="margin: 20px 30px"
    >
      <a-form-model-item
        :label="$t('ORIGIN_FIELD')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="originField"
      >
        <a-checkbox
          :indeterminate="stepThree.originIsIndeterminate"
          :checked="stepThree.originCheckAll"
          @change="stepThreeAllChange($event, 'origin')"
        >
          {{ $t("ALL_SELECT") }}
        </a-checkbox>
        <a-checkbox-group
          v-model="stepThreeForm.originField"
          :options="stepOneForm.fields"
          @change="stepThreeCheckedChange($event, 'origin')"
        />
      </a-form-model-item>
      <a-form-model-item
        :label="$t('TARGET_FIELD')"
        :label-col="{ span: 2 }"
        :wrapper-col="{ span: 10 }"
        prop="targetField"
      >
        <a-checkbox
          :indeterminate="stepThree.targetIsIndeterminate"
          :checked="stepThree.targetCheckAll"
          @change="stepThreeAllChange($event, 'target')"
        >
          {{ $t("ALL_SELECT") }}
        </a-checkbox>
        <a-checkbox-group
          v-model="stepThreeForm.targetField"
          :options="stepTwoForm.fields"
          @change="stepThreeCheckedChange($event, 'target')"
        />

        <!-- <a-checkbox
          v-model="stepThree.targetCheckAll"
          :indeterminate="stepThree.targetIsIndeterminate"
          @change="stepThreeAllChange($event, 'target')"
        >
          <span>{{ $t("ALL_SELECT") }}</span>
        </a-checkbox>
        <a-checkbox-group
          v-model="stepThreeForm.targetField"
          class="mb-15"
          @change="stepThreeCheckedChange($event, 'target')"
        >
          <a-checkbox
            v-for="field in stepTwoForm.fields"
            :key="field"
            :label="field"
          >
            {{ field }}
          </a-checkbox>
        </a-checkbox-group> -->
      </a-form-model-item>
    </a-form-model>

    <div v-show="active === 4" ref="stepFourForm" class="mt-10">
      <div class="mb-20">
        <a-button type="primary" @click="handleConstruct">
          <span>{{ $t("BUILD") }}</span>
        </a-button>
        <a-button type="info" @click="copyJson">
          <span
            ><span>{{ $t("COPY") }}</span> json</span
          >
        </a-button>
        <span>
          ({{ $t("STEP") }}：
          <span>{{ $t("BUILD") }}</span>
          <i class="el-icon-right" />
          <span>{{ $t("COPY") }}</span>
          json)
        </span>
      </div>
      <codemirror
        id="codemirror-code"
        v-model="code"
        class="codemirror"
        :options="cmOption"
      />
    </div>
  </div>
</template>

<script>
import { codemirror } from "vue-codemirror";
import "codemirror/lib/codemirror.css";
import Vue from "vue";
import VueClipBoard from "vue-clipboard2";
import ApiConstant from "@/api/ApiConstant";

Vue.use(VueClipBoard);
export default {
  name: "Construct",
  components: {
    codemirror,
  },
  data() {
    return {
      active: 1,
      formArr: ["stepOneForm", "stepTwoForm", "stepThreeForm", "stepFourForm"],
      dataSourceOptions: [],
      checkedList: ["Apple", "Orange"],
      indeterminate: true,
      checkAll: false,
      plainOptions: ["Apple", "Pear", "Orange"],
      stepOne: {
        tableOptions: [],
        fieldOptions: [],
        checkAll: false,
        isIndeterminate: true,
      },
      stepOneForm: {
        dataSource: "",
        jdbcUrl: "",
        table: "",
        preSql: "",
        querySql: "",
        fields: [],
        postSql: "",
        where: "",
      },

      stepTwo: {
        tableOptions: [],
        fieldOptions: [],
        checkAll: false,
        isIndeterminate: false,
      },
      stepTwoForm: {
        dataSource: "",
        jdbcUrl: "",
        table: "",
        fields: [],
        preSql: "",
        postSql: "",
      },
      stepThree: {
        originCheckAll: true,
        originIsIndeterminate: false,
        targetCheckAll: true,
        targetIsIndeterminate: false,
      },
      stepThreeForm: {
        originField: [],
        targetField: [],
      },
      cmOption: {
        tabSize: 2,
        styleActiveLine: true,
        lineNumbers: true,
        line: true,
        mode: {
          name: "javascript",
          json: true,
        },
        theme: "rubyblue",
      },
      code: null,
    };
  },
  computed: {
    stepOneRules() {
      return {
        dataSource: [
          {
            required: true,
            message: this.$t("PLACESELECT"),
            trigger: "change",
          },
        ],
        fields: [
          {
            type: "array",
            required: true,
            message: this.$t("PLACE_SELECT_FIELD"),
            trigger: "change",
          },
        ],
      };
    },
    stepTwoRules() {
      return {
        dataSource: [
          {
            required: true,
            message: this.$t("PLACESELECT"),
            trigger: "change",
          },
        ],
        fields: [
          {
            type: "array",
            required: true,
            message: this.$t("PLACE_SELECT_FIELD"),
            trigger: "change",
          },
        ],
      };
    },
    stepThreeRules() {
      return {
        originField: [
          {
            type: "array",
            required: true,
            message: this.$t("PLACE_SELECT_FIELD"),
            trigger: "change",
          },
        ],
        targetField: [
          {
            type: "array",
            required: true,
            message: this.$t("PLACE_SELECT_FIELD"),
            trigger: "change",
          },
        ],
      };
    },
  },
  created() {
    this.$axios
      .get(`${ApiConstant.PREFIX_CORE}/api/sys/datasource/list`)
      .then((res) => {
        this.dataSourceOptions = res.data.data;
      });
  },
  methods: {
    // 数据源切换 表格筛选项切换
    dataSourceChange(val, prop) {
      this.$axios
        .get(
          `${ApiConstant.PREFIX_CORE}/api/sys/datasource-query/tables/${val}`
        )
        .then((res) => {
          this[prop].tableOptions = res.data.data;
        });
      this[`${prop}Form`].table = "";

      this[`${prop}Form`].jdbcUrl = this.dataSourceOptions.find(
        (item) => item.id === val
      ).databaseUrl;
    },
    // 表格切换 表格字段筛选项切换
    tableChange(val, prop) {
      const { dataSource } = this[`${prop}Form`];
      this.$axios
        .get(`${ApiConstant.PREFIX_CORE}/api/sys/datasource-query/columns`, {
          params: {
            dataSourceId: dataSource,
            tableName: val,
          },
        })
        .then((res) => {
          this[prop].fieldOptions = res.data.data;

          this[prop].checkAll = true;
          this[prop].isIndeterminate = false;

          this[`${prop}Form`].fields = [...this[prop].fieldOptions];
        });
    },
    // querySql获取焦点
    querySqlFocus(prop) {
      this[prop].fieldOptions = [];

      this[prop].checkAll = false;
      this[prop].isIndeterminate = false;

      this[`${prop}Form`].fields = [];
    },
    querySqlBlur(prop) {
      const { dataSource, table } = this[`${prop}Form`];
      if (!this[`${prop}Form`].querySql && dataSource && table) {
        this.tableChange(table, prop);
      }
    },
    // 解析字段
    handleParseField() {
      const { dataSource: dataSourceId, querySql } = this.stepOneForm;
      if (!(dataSourceId && querySql)) {
        return;
      }

      this.$axios
        .get(
          `${ApiConstant.PREFIX_CORE}/api/sys/datasource-query/columns-query-sql`,
          {
            params: {
              dataSourceId,
              querySql,
            },
          }
        )
        .then((res) => {
          this.stepOne.fieldOptions = res.data.data;

          this.stepOne.checkAll = true;
          this.stepOne.isIndeterminate = false;

          this.stepOneForm.fields = [...this.stepOne.fieldOptions];
        });
    },

    handleCheckedChange(checkedList, prop) {
      this[`${prop}`].indeterminate =
        !!checkedList.length &&
        checkedList.length < this[`${prop}`].fieldOptions.length;
      this[`${prop}`].checkAll =
        checkedList.length === this[`${prop}`].fieldOptions.length;
    },
    onCheckAllChange(e, prop) {
      this[`${prop}Form`].fields = e.target.checked
        ? this[`${prop}`].fieldOptions
        : [];
      this[`${prop}`].indeterminate = false;
      this[`${prop}`].checkAll = e.target.checked;
    },

    handleCheckAllChange(e, prop) {
      this[`${prop}Form`].fields = e.target.checked
        ? this[`${prop}`].fieldOptions
        : [];
      this[`${prop}`].indeterminate = false;
      this[`${prop}`].checkAll = e.target.checked;
    },
    stepThreeAllChange(e, prop) {
      const options =
        prop === "target" ? this.stepTwoForm.fields : this.stepOneForm.fields;
      this.stepThreeForm[`${prop}Field`] = e.target.checked ? options : [];
      this.stepThree[`${prop}IsIndeterminate`] = false;
      this.stepThree[`${prop}CheckAll`] = e.target.checked;
    },
    stepThreeCheckedChange(value, prop) {
      const options =
        prop === "target" ? this.stepTwoForm.fields : this.stepOneForm.fields;
      const checkedCount = value.length;
      this.stepThree[`${prop}CheckAll`] = checkedCount === options.length;
      this.stepThree[`${prop}IsIndeterminate`] =
        checkedCount > 0 && checkedCount < options.length;
    },
    handlePrev() {
      if (this.active === 1) {
        return;
      }
      this.active -= 1;
    },
    async handleNext() {
      if (this.active >= 4) {
        return;
      }
      const valid = await this.$refs[this.formArr[this.active - 1]].validate();
      if (!valid) {
        return;
      }
      if (this.active === 2) {
        this.stepThreeForm.targetField = [...this.stepTwoForm.fields];
        this.stepThreeForm.originField = [...this.stepOneForm.fields];
      } else if (this.active === 3) {
        const { targetField, originField } = this.stepThreeForm;
        if (targetField.length !== originField.length) {
          this.$message.warning(this.$t("FIELD_LENGTH_DIFFERENT"));
          return;
        }
      }
      this.active += 1;
      if (this.active === 4) {
        this.code = "";
      }
    },
    // 构建
    handleConstruct() {
      const req = {
        rdbmsReader: {
          execute: {
            jdbcUrl: [this.stepOneForm.jdbcUrl],
            postSql: [this.stepOneForm.postSql],
            preSql: [this.stepOneForm.preSql],
          },
          querySql: this.stepOneForm.querySql,
          whereParams: this.stepOneForm.where,
        },
        rdbmsWriter: {
          preSql: this.stepTwoForm.preSql,
          postSql: this.stepTwoForm.postSql,
        },
        readerColumns: [...this.stepThreeForm.originField],
        readerDataSourceId: this.stepOneForm.dataSource,
        readerTables: [this.stepOneForm.table],
        writerColumns: [...this.stepThreeForm.targetField],
        writerDataSourceId: this.stepTwoForm.dataSource,
        writerTables: [this.stepTwoForm.table],
      };
      this.$axios
        .post(`/job-server/api/datax-json/build-json`, req)
        .then((res) => {
          this.code = JSON.stringify(JSON.parse(res.data.data), null, "\t");
        });
    },
    copyJson() {
      this.$copyText(this.code).then(
        () => {
          this.$message.success(this.$t("COPY_SUCCESS"));
        },
        () => {
          this.$message.success(this.$t("COPY_FAILED"));
        }
      );
    },
  },
};
</script>

<style lang="less" scoped>
.json-build-page {
  /deep/.CodeMirror {
    height: auto;
    min-height: 330px;
    color: #fff;
    background: #112435;
    border: 1px solid #eee;
    &-scroll {
      height: auto;
      min-height: 330px;
      overflow-x: auto;
      overflow-y: hidden;
    }
    .CodeMirror-gutters {
      background: #1f4661;
      border-right: 7px solid #3e7087;
    }
  }
}
.mb-12 {
  margin-bottom: 12px;
}
/deep/.ant-checkbox-wrapper {
  margin-left: 0 !important;
  margin-bottom: 10px;
  margin-right: 20px;
}
</style>
