<template>
  <div>
    <div class="ui header">
      <div class="ui breadcrumb">
        <a class="section" :href="`${repo}/modelmanage/show_model`">{{ $t('modelManage.modelManage') }}</a>
        <div class="divider"> / </div>
        <div class="active section">{{ this.state.name }}</div>
      </div>
      <div class="version">
        <el-select v-model="curVersion" @change="changeVersion" placeholder="">
          <el-option v-for="item in modelList" :value="item.version" :key="item.version" :label="item.version">
          </el-option>
        </el-select>
      </div>
    </div>
    <div class="content">
      <div class="detail-info">
        <div class="title">{{ $t('modelManage.basicInfo') }}：</div>
        <div class="area-c">
          <div class="area">
            <div class="row">
              <div class="tit">{{ $t('modelManage.useCluster') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.typeStr">
                  {{ state.typeStr }}
                </div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.modelSize') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.modelSize">{{ state.modelSize }}</div>
              </div>
            </div>
            <div class="row" :class="isEidtDescr ? 'edit-row' : ''">
              <div class="tit">{{ $t('modelManage.descr') }}：</div>
              <div class="val" :class="isEidtDescr ? 'edit-val' : ''">
                <div v-if="!isEidtDescr" class="txt-wrap" :title="state.description"
                  style="max-width:100%;width:unset;padding-right:20px;">
                  <span>{{ state.description }}</span>
                  <i v-if="canOperate" style="position:absolute;right:0;top:3px;color:rgb(22, 132, 252);cursor:pointer;"
                    class="el-icon-edit" @click="editDescr = state._description; isEidtDescr = true;"></i>
                </div>
                <div class="txt-edit" v-if="isEidtDescr">
                  <el-input type="textarea" v-model="editDescr" :maxLength="255"
                    :placeholder="$t('modelManage.modelDescrInputTips')"></el-input>
                  <i style="position:absolute;right:-4px;bottom:20px;color:rgb(255, 37, 37);cursor:pointer;"
                    class="icon times" @click="isEidtDescr = false;"></i>
                  <i style="position:absolute;right:-5px;bottom:2px;color:rgb(39, 177, 72);cursor:pointer;"
                    @click="submitEidt('descr')" class="icon check"></i>
                </div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.modelAccess') }}：</div>
              <div class="val">
                <div class="txt-wrap">{{ state.isPrivate }}</div>
              </div>
            </div>
          </div>
          <div class="area">
            <div class="row">
              <div class="tit">{{ $t('modelManage.modelEngine') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.engineName">{{ state.engineName }}</div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.createTime') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.createTime">{{ state.createTime }}</div>
              </div>
            </div>
            <div class="row" :class="isEidtLabel ? 'edit-row' : ''">
              <div class="tit">{{ $t('modelManage.label') }}：</div>
              <div class="val" :class="isEidtLabel ? 'edit-val' : ''">
                <div v-if="!isEidtLabel" class="txt-wrap" :title="state.label"
                  style="max-width:100%;width:unset;padding-right:20px;">
                  <span>{{ state.label }}</span>
                  <i v-if="canOperate" style="position:absolute;right:0;top:3px;color:rgb(22, 132, 252);cursor:pointer;"
                    class="el-icon-edit" @click="editLabel = state._label; isEidtLabel = true;"></i>
                </div>
                <div class="txt-edit" v-if="isEidtLabel">
                  <el-input v-model="editLabel" :maxLength="255" :placeholder="$t('modelManage.modelLabelInputTips')"
                    @input="labelInput"></el-input>
                  <i style="position:absolute;right:-5px;bottom:20px;color:rgb(255, 37, 37);cursor:pointer;"
                    class="icon times" @click="isEidtLabel = false;"></i>
                  <i style="position:absolute;right:-5px;bottom:2px;color:rgb(39, 177, 72);cursor:pointer;"
                    @click="submitEidt('label')" class="icon check"></i>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div v-show="isExpanded" style="margin-top:8px;" class="title">{{ $t('modelManage.trainTaskInfo') }}：</div>
        <div v-show="isExpanded" class="area-c">
          <div class="area">
            <div class="row">
              <div class="tit">{{ $t('modelManage.trainTask') }}：</div>
              <div class="val">
                <div class="txt-wrap" v-html="state.displayJobName"></div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.codeBranch') }}：</div>
              <div class="val">
                <div class="txt-wrap" v-html="state.branchName"></div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.bootFile') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.bootFile">{{ state.bootFile }}</div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.trainDataset') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.datasetName">{{ state.datasetName }}</div>
              </div>
            </div>
          </div>
          <div class="area">
            <div class="row">
              <div class="tit">{{ $t('modelManage.specInfo') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.specStr">{{ state.specStr }}</div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.workServerNumber') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.workServerNumber">{{ state.workServerNumber }}</div>
              </div>
            </div>
            <div class="row">
              <div class="tit">{{ $t('modelManage.runParameters') }}：</div>
              <div class="val">
                <div class="txt-wrap" :title="state.parameters">{{ state.parameters }}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="expand-line">
        <div class="line"></div>
        <div class="expand-btn" @click="isExpanded = !isExpanded">
          <i class="icon chevron circle down" :class="isExpanded ? 'up' : ''"></i>
          <span>{{ isExpanded ? $t('modelManage.collapseDetails') : $t('modelManage.seeMore') }}</span>
        </div>
        <div class="line"></div>
      </div>
      <div class="files-info">
        <div class="top">
          <div style="width:100%;margin-right:20px;">
            <div class="title">{{ $t('modelManage.modelFilesList') }}：</div>
            <div class="title files-path-c" style="margin-top:8px;margin-bottom:4px">
              <div class="file-path" v-for="(item, index) in filePath">
                <span v-if="index == filePath.length - 1" class="path-name">{{ item.label }}</span>
                <a v-if="index != filePath.length - 1" class="path-name canback" @click="goBackDir(item)">{{ item.label
                }}</a>
                <span style="color:rgba(0,0,0,.4);" class="divider"> / </span>
              </div>
            </div>
          </div>
          <div>
            <el-button v-if="modelType == 1 && canOperate" type="primary" icon="el-icon-upload" @click="goUploadPage">
              {{ $t('modelManage.uploadModelFiles') }}
            </el-button>
          </div>
        </div>
        <div class="table-container">
          <el-table ref="tableRef" :data="filesList" row-key="sn" style="width: 100%" v-loading="loading" stripe>
            <el-table-column column-key="FileName" prop="FileName" sortable
              :sort-method="(a, b) => a.FileName.toLocaleLowerCase().localeCompare(b.FileName.toLocaleLowerCase())"
              :label="$t('modelManage.fileName')" align="left" header-align="left">
              <template slot-scope="scope">
                <div class="tbl-file-name">
                  <a v-if="scope.row.IsDir" @click="goNextDir(scope.row)" href="javascript:;">
                    <div class="fitted" :title="scope.row.FileName">
                      <i class="icon folder" width="16" height="16" aria-hidden="true"></i>
                      <span>{{ scope.row.FileName }}</span>
                    </div>
                  </a>
                  <a v-else :class="!canDownload ? 'disabled-download' : ''"
                    :href="canDownload ? `${repo}/modelmanage/${state.id}/downloadsingle?parentDir=${filePath.length > 1 ? encodeURIComponent(filePath.map(item => item.path).join('/').slice(1) + '/') : ''}&fileName=${scope.row.FileName}` : 'javascript:;'">
                    <div class="fitted" :title="scope.row.FileName">
                      <i class="icon file" width="16" height="16" aria-hidden="true"></i>
                      <span>{{ scope.row.FileName }}</span>
                    </div>
                  </a>
                </div>
              </template>
            </el-table-column>
            <el-table-column column-key="SizeShow" prop="SizeShow" sortable :sort-method="(a, b) => a.Size - b.Size"
              :label="$t('modelManage.fileSize')" align="center" header-align="center" width="200">
            </el-table-column>
            <el-table-column column-key="ModTime" prop="ModTime" sortable
              :sort-method="(a, b) => a.ModTimeNum - b.ModTimeNum" :label="$t('modelManage.updateTime')" align="center"
              header-align="center" width="200">
            </el-table-column>
            <el-table-column v-if="modelType == 1 && canDelete" column-key="operate" prop="operate"
              :label="$t('modelManage.operate')" align="center" header-align="center" width="200">
              <template slot-scope="scope">
                <span v-if="!scope.row.IsDir" class="btn-del" @click="deleteFile(scope.row)">{{ $t('modelManage.delete')
                }}</span>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </div>
  </div>
</template>

<script>

import { getModelInfoByName, modifyModel, getModelFiles, deleteModelFile } from '~/apis/modules/modelmanage';
import { getUrlSearchParams, getListValueWithKey, transFileSize, renderSpecStr } from '~/utils';
import { MODEL_ENGINES } from '~/const';
import { formatDate } from 'element-ui/lib/utils/date-util';

const REPO_NAME = location.pathname.split('/')[2];
const MAX_LABEL_COUNT = 5;

export default {
  data() {
    return {
      modelType: '0', // 1-本地, 0-线上
      canOperate: false,
      canDownload:false,
      canDelete: false,
      isExpanded: false,
      loading: false,
      repo: location.pathname.split('/').slice(0, 3).join('/'),
      state: {
        type: 0,
        id: '',
        name: '',
        version: '0.0.1',
        engine: '0',
        label: '',
        description: '',
      },
      editDescr: '',
      isEidtDescr: false,
      editLabel: '',
      isEidtLabel: false,
      engineList: MODEL_ENGINES,
      curVersion: '',
      modelList: [],
      filesList: [],
      filePath: [],
    };
  },
  components: {},
  methods: {
    getDirFiles(dir) {
      dir = dir.length ? dir.slice(1) : '';
      getModelFiles({
        repo: this.repo,
        ID: this.state.id,
        parentDir: dir,
      }).then(res => {
        const list = res.data || [];
        list.forEach(item => {
          item.SizeShow = item.IsDir ? '' : transFileSize(item.Size);
          item.ModTimeNum = new Date(item.ModTime).getTime();
        })
        list.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
        this.filesList = list;
        this.$refs['tableRef']?.clearSort();
      }).catch(err => {
        console.log(err);
      });
    },
    goNextDir(item) {
      this.filePath.push({
        label: item.FileName,
        path: item.FileName
      });
      const dir = this.filePath.map((item) => item.path).join('/');
      this.getDirFiles(dir);
    },
    goBackDir(item) {
      const index = this.filePath.findIndex(pth => item === pth);
      this.filePath = this.filePath.slice(0, index + 1);
      const dir = this.filePath.map((item) => item.path).join('/');
      this.getDirFiles(dir);
    },
    changeVersion(version, noFileRefresh) {
      const data = this.modelList.filter((model) => model.version == version)[0];
      this.modelType = data.modelType;
      this.canOperate = data.isCanOper;
      this.canDownload = data.isCanDownload;
      this.canDelete = data.isCanDelete;
      this.state.type = data.type;
      this.state.typeStr = data.type == 0 ? 'CPU/GPU' : data.type == 1 ? 'NPU' : '';
      this.state.id = data.id;
      this.state.name = data.name;
      this.state.version = data.version;
      this.state.engine = data.engine.toString();
      this.state.engineName = getListValueWithKey(MODEL_ENGINES, data.engine.toString());
      this.state.modelSize = transFileSize(data.size);
      this.state.label = data.label || '--';
      this.state._label = data.label;
      this.state.description = data.description || '--';
      this.state._description = data.description;
      this.state.isPrivate= (data.isPrivate == true ? this.$t('modelManage.modelAccessPrivate'):this.$t('modelManage.modelAccessPublic'));
      this.state.createTime = formatDate(new Date(data.createdUnix * 1000), 'yyyy-MM-dd HH:mm:ss');

      const trainTaskInfo = data.trainTaskInfo ? JSON.parse(data.trainTaskInfo) : '';
      Object.assign(this.state, {
        displayJobName: '--',
        branchName: '--',
        bootFile: '--',
        datasetName: '--',
        parameters: '--',
        workServerNumber: '--',
        specStr: '--',
      });
      if (trainTaskInfo) {
        const parameters = trainTaskInfo.Parameters ? JSON.parse(trainTaskInfo.Parameters).parameter : [];
        const parametersStr = parameters.map((item) => { return item.label + '=' + item.value }).join('; ');
        const taskType = trainTaskInfo.Type;
        let taskUrl = location.href.split('modelmanage')[0];
        if (taskType == 0) {
          taskUrl = taskUrl + 'cloudbrain/train-job/' + trainTaskInfo.JobID;
        } else if (taskType == 1) {
          taskUrl = taskUrl + 'modelarts/train-job/' + trainTaskInfo.JobID;
        } else if (taskType == 2) {
          taskUrl = taskUrl + 'grampus/train-job/' + trainTaskInfo.JobID;
        }
        const versionName = trainTaskInfo.VersionName;
        const versionHtml = versionName ? `<span class="append-txt" title="${versionName}">${versionName}</span>` : '';
        const codeCommitID = data.codeCommitID;
        const codeCommitIDHtml = codeCommitID ? `<span class="append-txt" title="${codeCommitID}">${codeCommitID.slice(0, 10)}</span>` : '';
        let specObj;
        try {
          specObj = trainTaskInfo.FlavorName ? JSON.parse(trainTaskInfo.FlavorName) : '';
        } catch (e) {
          specObj = trainTaskInfo.FlavorName;
        }
        const sepcStr = typeof specObj == 'object' ? renderSpecStr(specObj, false) : specObj;
        Object.assign(this.state, {
          displayJobName: `<a href="${taskUrl}" title="${trainTaskInfo.DisplayJobName}">${trainTaskInfo.DisplayJobName}</a>${versionHtml}`,
          branchName: `<span>${trainTaskInfo.BranchName}</span>${codeCommitIDHtml}`,
          bootFile: trainTaskInfo.BootFile,
          datasetName: trainTaskInfo.DatasetName,
          parameters: parametersStr || '--',
          workServerNumber: trainTaskInfo.WorkServerNumber || '1',
          specStr: sepcStr || '--',
        });
      }
      this.curVersion = version;
      if (!noFileRefresh) {
        this.filePath = [{ label: version, path: '' }];
        this.getDirFiles('')
      }
    },
    goUploadPage() {
      window.location.href = `${this.repo}/modelmanage/create_local_model_2?type=1&name=${encodeURIComponent(this.state.name)}&id=${this.state.id}`;
    },
    backToModelListPage() {
      const list = window.location.href.split('/');
      list.pop();
      list.push('show_model');
      window.location.href = list.join('/');
    },
    labelInput() {
      const hasEndSpace = this.editLabel[this.editLabel.length - 1] == ' ';
      const list = this.editLabel.trim().split(' ').filter(label => label != '');
      this.editLabel = list.slice(0, MAX_LABEL_COUNT).join(' ') + (hasEndSpace && list.length < MAX_LABEL_COUNT ? ' ' : '');
    },
    submitEidt(type) {
      const obj = {
        repo: this.repo,
        type: this.state.type,
        id: this.state.id,
        name: this.state.name,
        version: this.state.version,
        engine: this.state.engine,
        label: type == 'label' ? this.editLabel : this.state.label,
        description: type == 'descr' ? this.editDescr : this.state.description,
      };
      modifyModel(obj).then(res => {
        res = res.data;
        if (res && res.code == '0') {
          if (type == 'label') {
            this.state.label = this.editLabel;
            this.state._label = this.editLabel;
            this.isEidtLabel = false;
          } else if (type == 'descr') {
            this.state.description = this.editDescr;
            this.state._description = this.editDescr;
            this.isEidtDescr = false;
          }
        } else {
          this.$message({
            type: 'error',
            message: this.$t('modelManage.infoModificationFailed'),
          });
        }
      }).catch(err => {
        console.log(err);
        this.$message({
          type: 'error',
          message: this.$t('modelManage.infoModificationFailed'),
        });
      });
    },
    deleteFile(file) {
      this.$confirm(this.$t('modelManage.deleteModelFileConfirmTips'), this.$t('tips'), {
        confirmButtonText: this.$t('confirm1'),
        cancelButtonText: this.$t('cancel'),
        type: 'warning',
        lockScroll: false,
      }).then(() => {
        this.loading = true;
        deleteModelFile({
          repo: this.repo,
          id: this.state.id,
          fileName: file.FileName,
        }).then(res => {
          res = res.data;
          if (res.code == '0') {
            setTimeout(() => {
              this.loading = false;
              this.updateModelInfo();
              const dir = this.filePath.map((item) => item.path).join('/');
              this.getDirFiles(dir);
            }, 30);
          } else {
            this.loading = false;
            this.$message({
              type: 'error',
              message: this.$t('modelManage.modelFileDeleteFailed'),
            });
          }
        }).catch(err => {
          console.log(err);
          this.$message({
            type: 'error',
            message: this.$t('modelManage.modelFileDeleteFailed'),
          });
        });
      }).catch(() => { });
    },
    updateModelInfo() {
      getModelInfoByName({
        repo: this.repo,
        name: this.state.name,
      }).then(res => {
        const list = res.data || [];
        this.modelList = list;
        const noFileRefresh = true;
        this.changeVersion(this.curVersion, noFileRefresh);
      }).catch(err => {
        console.log(err);
      });
    },
  },
  mounted() {
    const urlParams = getUrlSearchParams();
    if (urlParams.name) {
      this.state.name = urlParams.name;
      this.loading = true;
      getModelInfoByName({
        repo: this.repo,
        name: urlParams.name,
      }).then(res => {
        this.loading = false;
        const list = res.data || [];
        this.modelList = list;
        if (list && list.length) {
          const data = list[0];
          this.changeVersion(data.version);
        }
      }).catch(err => {
        this.loading = false;
        console.log(err);
        this.backToModelListPage();
      });
    } else {
      this.backToModelListPage();
    }
  },
  beforeDestroy() {
  },
};
</script>

<style scoped lang="less">
.header {
  display: flex;
  align-items: center;

  .version {
    margin-left: 16px;
    width: 90px;
  }
}

.content {
  .title {
    font-weight: 550;
    font-size: 14px;
    color: rgb(16, 16, 16);
    margin-bottom: 10px;
  }

  .detail-info {
    border: 1px solid rgb(232, 232, 232);
    border-bottom: none;
    padding: 22px;
    padding-bottom: 1px;

    .area-c {
      display: flex;

      .area {
        flex: 1;

        .row {
          display: flex;
          height: 32px;
          margin-bottom: 4px;
          align-items: center;

          &.edit-row {
            height: unset;
          }

          .tit {
            width: 160px;
            text-align: right;
            color: rgb(136, 136, 136);
          }

          .val {
            flex: 1;
            color: rgb(16, 16, 16);
            position: relative;
            height: 20px;

            &.edit-val {
              height: unset;
            }

            .txt-wrap {
              position: absolute;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
              width: 100%;

              /deep/.append-txt {
                margin-left: 6px;
                background-color: gainsboro;
                padding: 2px;
                border-radius: 2px;
                font-size: 12px;
              }
            }
          }

          .txt-edit {
            padding-right: 20px;
          }
        }
      }
    }
  }

  .expand-line {
    display: flex;
    align-items: center;
    border: 1px solid rgb(232, 232, 232);
    border-top: none;
    border-bottom: none;
    padding: 16px 0;

    .line {
      flex: 1;
      height: 1px;
      background-color: rgb(232, 232, 232);
      margin: 0 22px;
    }

    .expand-btn {
      color: rgba(22, 132, 252, 1);
      cursor: pointer;

      .icon {
        margin-right: 2px;
        font-size: 14px;
        color: rgba(22, 132, 252, 0.8),
      }
    }
  }


  .files-info {
    border: 1px solid rgb(232, 232, 232);
    border-top: none;
    border-bottom: none;

    .top {
      padding: 0 22px 8px 22px;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .files-path-c {
      margin-bottom: 4px;
      height: 20px;

      .file-path {
        margin-right: 6px;
        float: left;

        .path-name {
          &.canback {
            color: #4183c4;
          }
        }
      }
    }

    .table-container {
      /deep/ .el-table__header {
        th {
          background: rgb(245, 245, 246);
          color: rgb(16, 16, 16);
          font-weight: 400;
          font-size: 14px;
        }
      }

      /deep/ .el-table__body {
        td {
          color: rgb(16, 16, 16);
          font-weight: 400;
          font-size: 14px;
        }
      }

      .tbl-file-name {
        height: 32px;
        display: flex;
        align-items: center;
        overflow: hidden;
        font-size: 16px;
        font-weight: 500;
        position: relative;

        a {
          max-width: 100%;

          .fitted {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            max-width: 100%;
          }
        }

        .disabled-download {
          cursor: default;
          pointer-events: none;
          color: rgba(0, 0, 0, .6) !important;
          opacity: .45 !important;
        }
      }

      .btn-del {
        color: #0366d6;
        cursor: pointer;
      }
    }
  }
}


.el-select-dropdown__item.selected {
  color: rgba(0, 0, 0, .95);
}

/deep/ .el-select {
  .is-focus {
    .el-input__inner {
      border-color: #85b7d9;
    }
  }
}

.el-select {
  /deep/ .el-input__inner {
    font-weight: 600;
  }
}

/deep/ .el-input__inner {
  &:focus {
    border-color: #85b7d9;
  }
}

/deep/ .el-textarea__inner {
  &:focus {
    border-color: #85b7d9;
  }
}
</style>
