<template>
  <div class="flex-h  query-designer">
    <Panel title="选择数据表" class="table-list" v-loading="view.tableList.loading">
      <template slot="buttons">
        <el-button icon="el-icon-fa-refresh " class="blue" @click="handleLoadTable"/>
        <el-button icon="el-icon-fa-close " class="red" @click="handleUnselect"/>
      </template>
      <el-input class="table-list__filter" v-model="meta.tableFilter" placeholder="过滤表" clearable/>

      <div class="table-list__lists">
        <el-checkbox-group class="table-list__tables" v-model="meta.selectedTables" :max="7" @change="onSelectTable">
          <el-checkbox v-for="tableInfo in filterBy(meta.tables,meta.tableFilter)"
                       :key="tableInfo.tableName"
                       :label="tableInfo">
            {{tableInfo.tableName}}
          </el-checkbox>
        </el-checkbox-group>
      </div>
    </Panel>


    <Panel title="查询设计" class="work-space flex-1" v-loading="view.tableList.loading">
      <template slot="buttons">
        <el-button icon="el-icon-fa-save" type="primary" @click="handleSave">保存</el-button>
      </template>

      <div class="flex-v">

        <!--  表列表区域 -->
        <div class="work-space__select-tables">
          <div class="work-space__table"
               v-for="(table,idx) in meta.selectedTables"
               :key="table.tableName"
               v-loading="table.loading">
            <div class="work-space__table__header" :class="{'master':table.master}">
              <span class="work-space__table__title" :title="table.tableName">
                {{table.tableName}}
              </span>
              <span class="work-space__table__buttons">
                 <el-button type="primary" @click="handleSetMaster(idx)" v-if="!table.master">主</el-button>
                <el-button icon="el-icon-close" type="danger" @click="handleRemoveTable(idx)"/>
              </span>
            </div>

            <div class="work-space__table__body">
              <el-checkbox-group class="table-list__tables" v-model="table.selectedColumns" @change="onSelectColumn">
                <el-checkbox v-for="column in table.columns"
                             :key="column.columnName"
                             :label="column">
                  {{column.columnName}}
                </el-checkbox>
              </el-checkbox-group>
            </div>
          </div>
        </div>

        <div class="flex-h">
          <!--  SQL预览区域 -->
          <Panel title="SQL预览" style="width: 460px">
            <template slot="buttons">
              <!--               <el-button icon="el-icon-fa-copy" ref="copySqlButton"/>-->
            </template>
            <div class="work-space__sql" style="height: 405px;overflow: auto">

              <!-- SELECT  -->
              <div class="bg-select ">
                <span class="work-space__key-world">SELECT</span>
                <span class="work-space__normal-key" :class="{'optional':!properties.distinct}" @click="properties.distinct=!properties.distinct">Distinct</span>
                <div class="work-space__diy-sql">
                  <template v-for="(table) in meta.selectedTables" v-if="table.selectedColumns.length>0">
                    <div v-for="(field,idx) in table.selectedColumns" :key="table.tableName + idx">
                      <span class="block-input" style=" min-width: 230px;">{{table.alias}}.{{field.columnName}}</span>
                      <span class="block-input" style=" min-width: 30px;">as</span>
                      <input class="join-input" style="width: 90px" type="text" v-model='field.alias'/>
                      <span class="block-input" style=" min-width: 10px;text-align: right">,</span>
                    </div>
                  </template>
                </div>
              </div>

              <!-- FROM  -->
              <div class="bg-from padding-top-1">
                <template v-for="(table) in meta.selectedTables" v-if="table.selectedColumns.length>0 && table.master">
                  <div :key="table.tableName" class="bg-script">
                    <span class="work-space__key-world">FROM</span>
                    <span class="block-input" style=" width: 260px;"> {{table.tableName}} </span>
                    <input class="join-input" style=" width: 100px;" v-model="table.alias"/>
                  </div>
                </template>
              </div>


              <!-- LEFT JOIN  -->
              <div class="bg-from padding-top-1">
                <template v-for="(table) in meta.selectedTables" v-if="table.selectedColumns.length>0 && !table.master">
                  <div :key="table.tableName" class="bg-script">
                    <span class="work-space__key-world  ">LEFT JOIN</span>
                    <span class="block-input" style=" width: 260px;"> {{table.tableName}} </span>
                    <input class="join-input" style=" width: 100px;" v-model="table.alias"/>
                    <span class="work-space__key-world ">ON</span>
                    <input class="join-input" style="width: 360px" v-model="table.on"/>
                  </div>
                </template>
              </div>

              <!-- WHERE  -->
              <div class="bg-where padding-top-1">
                <div>
                  <span class="work-space__key-world  ">WHERE</span>
                  <input class="join-input" style="width: 360px" type="textarea" v-model='properties.where'/>
                </div>
                <div>
                  <span class="work-space__key-world  ">GROUP BY</span>
                  <input class="join-input" style="width: 360px" type="textarea" v-model='properties.groupBy'/>
                </div>
                <div>
                  <span class="work-space__key-world  ">HAVING</span>
                  <input class="join-input" style="width: 360px" type="textarea" v-model='properties.having'/>
                </div>
                <div>
                  <span class="work-space__key-world  ">ORDER BY</span>
                  <input class="join-input" style="width: 360px" type="textarea" v-model='properties.orderBy'/>
                </div>
              </div>
            </div>
          </Panel>

          <div class="flex-1 flex-v">

            <Panel title="查询属性">
              <el-form :model="properties" ref="propertiesForm" :rules="propertiesRules" label-position='right' label-width="70px">
                <div class="flex-h">
                  <el-form-item class="flex-1" label="查询标题" prop="queryTitle">
                    <el-input v-model="properties.queryTitle" maxlength='100'/>
                  </el-form-item>
                </div>
              </el-form>
            </Panel>


            <Panel title="查询条件" class="flex-1" >
              <el-table :data="conditions" border  >
                <el-table-column prop="field" label="查询字段">
                  <template slot-scope="{row}">{{row.column.alias}}</template>
                </el-table-column>
                <el-table-column prop="symbol" label="比较方式">
                  <template slot-scope="{row}">
                    <el-select v-model="row.column.searchExpr">
                      <el-option v-for="item in expressions" :key="item.value" :label="item.label" :value="item.value"/>
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column prop="type" label="参数类型">
                  <template slot-scope="{row}">
                    <div class="flex-h">
                      <el-select class="flex-1" v-model="row.column.searchType">
                        <el-option v-for="item in paramTypes" :key="item.value" :label="item.label" :value="item.value"/>
                      </el-select>
                      <el-input  class="flex-1 margin-left-1" placeholder="字典名"  v-if="row.column.searchType==='Dict'" v-model="row.column.searchDict"/>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column prop="type" label="操作" width="40" align="center">
                  <template slot-scope="{row,index}">
                    <el-button icon="el-icon-fa-remove" @click="handleRemoveCnd(row)"/>
                  </template>
                </el-table-column>
              </el-table>
            </Panel>
          </div>
        </div>
      </div>

    </Panel>
  </div>
</template>
<script>
  import QueryAPI from "@/api/base/sysm/QueryAPI";

  export default {
    props: {
      uuid: String
    },
    data() {
      return {
        meta: {
          selectedTables: [],
          tables: [],
          tableFilter: ""
        },
        paramTypes: [
          {value: "String", label: "字符串"},
          {value: "Number", label: "数字"},
          {value: "Date", label: "日期"},
          {value: "DateTime", label: "时间"},
          {value: "Dict", label: "数据字典"},
        ],
        expressions: [
          {value: "eq", label: "等于"},
          {value: "like", label: "模糊"},
          {value: "range", label: "范围"}
        ],
        properties: {
          uuid: "",
          queryName: "",
          queryTitle: "",
          distinct: false,
          sql: "",
          where: "",
          groupBy: "",
          having: "",
          orderBy: "",
          fields: [],
          tables: []
        },
        propertiesRules: {
          queryName: [{required: true, message: "请为查询命名"}],
          queryTitle: [{required: true, message: "请为录入查询标题"}],
        },
        view: {
          tableList: {
            loading: false
          }
        }
      };
    },
    watch: {},
    computed: {
      conditions() {
        return this.meta.selectedTables
            .filter(value => value.selectedColumns.length > 0)
            .flatMap(table => {
              return table.selectedColumns.map(column => ({table, column}));
            })
      }
    },
    async mounted() {
      await this.handleLoadTable();
    },
    methods: {
      handleSaveData() {
        let fields = [];
        let tables = [];

        let selectedTables = [];
        // 先放入主表
        this.meta.selectedTables
            .filter(value => value.master)
            .forEach(value => selectedTables.push(value));

        //再放入从表
        this.meta.selectedTables
            .filter(value => !value.master)
            .forEach(value => selectedTables.push(value));

        selectedTables
            .filter(value => value.selectedColumns.length > 0)
            .forEach((tab, index) => {

              tab.alias = tab.alias || 'tab' + (tables.length + 1);

              tab.selectedColumns.forEach((col, index) => {
                col.alias = col.alias || 'col' + (fields.length + 1);
                col.tableAlias = tab.alias;

                fields.push({
                  table: tab.alias,
                  tableName:tab.tableName,
                  column: col.columnName,
                  alias: col.alias,
                  searchExpr: col.searchExpr,
                  searchType: col.searchType,
                  searchDict: col.searchDict,
                });

              });

              tables.push({
                tableName: tab.tableName,
                master: tab.master,
                alias: tab.alias,
                on: tab.on,
              });

            });
        Object.assign(this.properties, {
          fields,
          tables
        });
        return this.properties;
      },
      async handleSave() {
        await this.$refs['propertiesForm'].validate();
        let data = this.handleSaveData();
        delete data['defineJson'];
        data.defineJson = JSON.stringify(this.properties);
        let resp = await QueryAPI.saveDesign(data);
        this.properties.sql = resp.sql;
        this.properties.uuid = resp.uuid;
        this.$emit("save", data);
      },
      async handleLoadTable() {
        if (this.uuid) {
          let data = await QueryAPI.loadDesign(this.uuid);
          Object.assign(this.properties, data);
          this.properties.uuid = this.uuid;
        }
        try {
          this.view.tableList.loading = true;
          let data = await QueryAPI.loadAllTable();
          data.forEach((value, index) => {
            value.columns = [];
            value.selectedColumns = [];
            value.loading = false;
            value.selected = false;
            value.alias = "";
            value.master = false;
            value.on = "";

            //  被选中数据
            this.properties.tables.forEach(table => {
              if (table.tableName === value.tableName) {
                value.on = table.on;
                value.alias = table.alias;
                value.master = table.master;
                this.meta.selectedTables.push(value);
              }
            })
          });
          this.meta.tables = data;
          this.onSelectTable()
        } finally {
          this.view.tableList.loading = false;
        }
      },
      handleUnselect() {
        this.meta.selectedTables.splice(0);
        this.meta.wheres = [];
      },
      handleRemoveTable(idx) {
        this.meta.selectedTables.splice(idx, 1);
      },
      handleSetMaster(idx) {
        this.meta.selectedTables
            .filter(value => value.master)
            .forEach(value => value.master = false);
        this.meta.selectedTables[idx].master = true;
        this.handleSaveData();
      },
      onSelectColumn() {
        this.handleSaveData();
      },
      onSelectTable() {
        this.meta.selectedTables
            .filter(value => value.columns.length === 0)
            .forEach(this.loadColumns);
        //只选中了一张表,则设置为主表
        if (this.meta.selectedTables.length === 1) {
          this.meta.selectedTables[0].master = true;
        }
      },

      async loadColumns(table) {
        table.loading = true;
        let data = await QueryAPI.listColumns(table.tableName);
        data.forEach((value, index) => {
          value.selected = false;
          value.alias = "";
          value.field = "";
          value.searchExpr = "";
          value.searchType = "";
          value.searchDict = "";
          value.table = table.tableName;

          /* 匹配字段选中 */
          let proptable = this.properties.tables.find(pt => value.table === pt.tableName);
          let field = this.properties.fields.find(field => field.table === proptable.alias && field.column === value.columnName);

          if (field) {
            value.alias = field.alias;
            value.searchExpr = field.searchExpr;
            value.searchType = field.searchType;
            value.searchDict = field.searchDict;
            table.selectedColumns.push(value);
          }
        });
        table.columns = data;
        table.loading = false;
      },
      handleRemoveCnd(row) {
        row.column.searchExpr = "";
        row.column.searchType = "";
      }
    }
  };
</script>

<style lang="scss">
  .query-designer {

    .check-list {
      overflow-x: hidden;
      overflow-y: auto;

      .el-checkbox {
        display: block;
        margin: 0;
        padding: 0 3px;
        text-transform: uppercase;
        transition: 0.2s background-color;

        &__label {
          font-size: 12px;
        }

        &:hover {
          background-color: #ccc;
          font-weight: bold;
        }
      }
    }

    .la-panel {
      border-radius: 0;
    }

    .la-panel__header {
      border-radius: 0;
    }

    .table-list {
      width: 200px;
      @extend .check-list;

      .la-panel__body {
        padding: 0;
      }

      &__lists {
        height: 662px;
      }

      &__filter {
        width: 98%;
        border: none;
        padding: 1%;

        input {
          border-radius: 0;
        }
      }


    }

    .work-space {
      .la-panel__header {
        input {
          outline: none;
        }
      }

      .la-panel__body {
        padding: 0;
      }

      &__select-tables {
        height: 240px;
      }

      &__table {
        width: 178px;
        height: 230px;
        display: inline-block;
        margin: 3px;
        border: 1px solid #409EFF;
        cursor: default;
        position: relative;

        &__header {
          position: absolute;
          width: 100%;
          background: #c2f1ff;
          color: black;
          padding: 2px;
          box-sizing: border-box;

          &.master {
            background: #409EFF;
          }
        }

        &__title {
          width: 70%;
          display: inline-block;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          font-size: 12px;
        }

        &__buttons {
          float: right;

          .el-button {
            padding: 1px;
            border-radius: 0;
          }
        }

        &__body {
          margin-top: 20px;
          height: 210px;
          @extend .check-list;
        }
      }

      &__sql {
        font-size: 14px;
        color: black;
        /*text-transform: lowercase;*/
      }

      &__diy-sql {
        margin-left: 80px;
        /*text-transform: lowercase;*/
      }


      .join-input {
        font-size: 12px;
        border-width: 0 0 1px 0;
        border-style: solid;
        border-color: #91d4de;
        outline: none;
        background: transparent;
      }

      .block-input {
        font-size: 12px;
        border: none;
        outline: none;
        display: inline-block;
        background: transparent;
      }

      .bg-select {
        background-color: whitesmoke;
      }

      .bg-from {
        background-color: floralwhite;
      }

      .bg-script {
        padding: 1px 0 1px 0;
        margin: 1px 0 1px 0;
        background-color: rgba(238, 232, 224, 0.98);
      }

      .bg-where {
        background-color: antiquewhite;
      }


      &__key-world {
        text-transform: lowercase;
        color: #2f46ff;
        font-weight: bold;
        margin-right: 20px;
        display: inline-block;
        width: 60px;
        text-align: right;
        font-size: 12px;
      }


      &__normal-key {
        color: #476bff;

        &.optional {
          &:before {
            content: "<";
          }

          &:after {
            content: ">";
          }

          &:hover {
            color: black;
          }

          cursor: pointer;
          color: gray;
        }
      }
    }
  }
</style>
