<template>
  <div class="demo-collapse">
    <div class="containers">
      <div class="left">
        <div class="ml-4">协议版本</div>
        <el-select v-model="currentVersion" @change="changeProtocolVersion" ml-4>
          <el-option
            v-for="option in options"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          >
          </el-option>
        </el-select>
        <el-button @click="newVersionDialog = true" icon="plus" ml-4>新增版本</el-button>
      </div>
      <div class="right">
        <el-upload
          v-if="isUpload"
          action="/api/protocol_version_manage/file_upload/"
          :show-file-list="false"
          :data="{
            protocol_name: props.name,
            version: currentVersion
          }"
          :on-success="uploadFileSuccess"
          :on-error="uploadFileFail"
          mr-4>
          <el-button icon="upload">上传原始文件</el-button>
        </el-upload>
        <el-button v-else @click="downloadFile" icon="download"> 下载原始文件 </el-button>

        <el-button @click="addCmdDialog = true" icon="plus">新增指令</el-button>
        <!-- <el-button @click="deleteProtocol">删除该版本协议</el-button> -->
      </div>
    </div>


    <el-collapse class="mt-4 collapse1" accordion>
      <el-collapse-item

        v-for="cmd in cmdInfos">
        <template #title>
          <div style="width:100%; display: flex; justify-content: space-between">
            <div ml-4>{{cmd.cmd_name + ' ' + cmd.cmd_explain + ' ' + cmd.cmd_type }}</div>
            <div>
              <el-button text type="danger" icon="delete" ml-4 @click="removeCmd(cmd.id)">删除指令</el-button>
            </div>
          </div>

        </template> 
        <protocol-table
          v-if="fieldInfos !== undefined" 
          :cmd-name="cmd.cmd_name" 
          :version="currentVersion"
          :protocol-name="props.name"
          :cmd-type="cmd.cmd_type"
          :message="fieldInfos[cmd.cmd_name]" />
      </el-collapse-item>
    </el-collapse>

    <el-dialog v-model="addCmdDialog" title="新增指令">
      <el-form :model="addCmdData">
        <el-form-item prop="cmd_name" label="指令名称" :label-width="formLabelWidth">
          <el-input v-model="addCmdData.cmd_name" autocomplete="off" />
        </el-form-item>
        <el-form-item prop="cmd_type" label="指令类型" :label-width="formLabelWidth">
          <el-select v-model="addCmdData.cmd_type">
            <el-option label="TX" value="TX"></el-option>
            <el-option label="RX" value="RX"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item prop="encode" label="协议类型" :label-width="formLabelWidth">
          <el-select v-model="addCmdData.encode">
            <el-option label="ASCII" value="ASCII"></el-option>
            <el-option label="HEX" value="HEX"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item prop="timing_cmd_cycle_period" label="定时发送(单位s)" :label-width="formLabelWidth">
          <el-input v-model="addCmdData.timing_cmd_cycle_period" autocomplete="off" />
        </el-form-item>
        <el-form-item prop="cmd_explain" label="说明" :label-width="formLabelWidth">
          <el-input v-model="addCmdData.cmd_explain" autocomplete="off" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="addCmdDialog = false">取消</el-button>
          <el-button type="primary" @click="addCmd">
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>

    <el-dialog v-model="newVersionDialog" :width="500" title="新增协议版本">
      <el-form :model="newVersionForm">
        <el-form-item prop="versionName" label="版本名称" :label-width="formLabelWidth">
          <el-input v-model="newVersionForm.versionName" autocomplete="off" />
        </el-form-item>
        <el-form-item prop="isExtend" label="是否继承版本" :label-width="formLabelWidth">
          <el-switch v-model="newVersionForm.isExtend" />
        </el-form-item>
        <el-form-item v-show="newVersionForm.isExtend" prop="extendVersionName" label="继承版本名称" :label-width="formLabelWidth">
          <el-select v-model="newVersionForm.extendVersionName">
            <el-option
              v-for="option in options"
              :label="option.label"
              :value="option.value"
            >
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="newVersionDialog = false">取消</el-button>
          <el-button type="primary" @click="addNewVersion"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue'
import { ElMessage, ElMessageBox } from "element-plus";
import { ProtocolInit, addCmdDao, removeCmdDao } from "@/dao/protocol"
import ProtocolTable from "./ProtocolTable.vue";
import type { DeviceProtocolResponse, ProtocolCmdResponse } from './types';
import { useProtocolVersionStore } from '@/stores/allProtocolVersion';
import axios from 'axios';
import request from '@/plugins/axios/requests';

const addCmdDialog = ref<boolean>(false)
const currentVersion = ref('')
type OptionType = {
  value: string
  label: string
}
const options = ref<OptionType[]>([])
const formLabelWidth = '140px'

type propsType = {
  info: DeviceProtocolResponse,
  name: string,
  protocolCmd: ProtocolCmdResponse
}
const props = defineProps<propsType>()

function Init(){
  ProtocolInit({protocol_name: props.name})
      .then((_) => {
        options.value.push({value: "init", label: "init"})
        currentVersion.value = "init"
      })
      .catch((err) => {
        console.log(err);
      })
}

const store = useProtocolVersionStore()
const cmdInfos = ref()
const fieldInfos = ref<Record<string, any>>({})
const isUpload = ref(true)
// 需要延时一下，不然 store 里面的数据可能没有被赋值上去，组件就被渲染了
onMounted(() => setTimeout(() => {
  // 判断是否需要初始化
  let flag = true

  cmdInfos.value = props.info[props.name]
  // 将 props.protocolCmd 转成 Record<string, any> 类型, 统一类型，方便后面过来的数据操作
  for (const [key, value] of Object.entries(props.protocolCmd)){
    fieldInfos.value[key] = value
  } 

  // 对 options 添加协议的版本
  let version_paths
  for (let protocolVersion of store.protocolVersions){
    if (protocolVersion.protocol_name === props.name) {
      version_paths = JSON.parse(protocolVersion.version_paths)
      for (let version_path of version_paths){
        options.value.push({value: version_path.version, label: version_path.version})
      }

      flag = false
      break
    }
  }

  // 设置当前协议版本
  if (!flag) {
    for (let item of store.currentVersions){
      if (item.protocol_name === props.name) {
        currentVersion.value = item.version
        break
      }
    }
  }

  // 如果需要初始化
  if (flag){
    Init()
  }

  // 更新上传下载按钮
  for (let version_path of version_paths) {
    if (version_path.version === currentVersion.value) {
      if (version_path.path !== undefined) {
        isUpload.value = false
      } else {
        isUpload.value = true
      }
    }
  }  
}, 50))

// 修改协议版本
const changeProtocolVersion = () => {
  axios.post('/api/protocol_version_manage/change_protocol_version/',
  {
    version: currentVersion.value,
    protocol_name: props.name,
  })
  .then((res) => {
    console.log(res);
    
    const { cmds } = res.data 
    cmdInfos.value = cmds
    // 转成和上面 ProtocolCmdResponse 一样的类型
    for (let cmd of cmds) {
      const { fields, ...info} = cmd
      fieldInfos.value[info.cmd_name] = fields
    }

    // 修改按钮文件
    for (let protocolVersion of store.protocolVersions){
      if (protocolVersion.protocol_name === props.name) {
        const version_paths = JSON.parse(protocolVersion.version_paths)
        for (let version_path of version_paths){
          if (version_path.version === currentVersion.value) {
            if (version_path.path !== undefined) {
              isUpload.value = false
            } else {
              isUpload.value = true
            }
          }
        }
      }
    }
  })
  .catch((err) => {
    console.log(err);
  })
}

// 文件上传下载相关
const uploadFileSuccess = () => {
  isUpload.value = false
  ElMessage({
    type: 'success',
    message: '上传成功',
  })
}

const uploadFileFail = () => {
  ElMessage({
    type: 'error',
    message: '上传失败',
  })
}

const downloadFile = () => {
  let url = `/api/protocol_version_manage/file_download/${props.name}/${currentVersion.value}/`;
  axios({
    url,
    method: "GET",
    responseType: "blob",
  }).then((res) => {
    // 下载文件
    console.log(res);
    const blob = new Blob([res.data], { type: "multipart/form-data" });
    const link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = decodeURIComponent(res.headers["filename"]);
    link.click();
  });
  console.log("downloadFile");
};

// 删除协议的某个版本
// const deleteProtocol = () => {
//   console.log(currentVersion.value, props.name);
//   axios.post('/api/protocol_vesrion_manage/delete_protocol_vesrion/',
//   {
//     version: currentVersion.value,
//     protocol_name: props.name,
//   })
//   .then(() => {
//     ElMessage({
//       type: 'success',
//       message: '删除成功',
//     })
//     options.value = options.value.filter((item) => item.value !== currentVersion.value)
//     currentVersion.value = options.value[0].value
//     changeProtocolVersion()
//   })
//   .catch((err) => {
//     console.log(err);
//     ElMessage.error('删除失败')
//   })
// }

// 新增协议指令
const addCmdData = reactive({
  cmd_name: '',
  cmd_type: '',
  encode: '',
  timing_cmd_cycle_period: '',
  cmd_explain: '',
})
const addCmd = () => {
  ElMessageBox.confirm(
    '是否确认增加？',
    'Warning',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
  .then(() => {
    addCmdDao({
      protocol_name: props.name,
      cmd_name: addCmdData.cmd_name,
      cmd_type: addCmdData.cmd_type,
      encode: addCmdData.encode,
      timing_cmd_cycle_period: addCmdData.timing_cmd_cycle_period,
      cmd_explain: addCmdData.cmd_explain,
      version: currentVersion.value,
    })
    .then((res) => {
      ElMessage({
        type: 'success',
        message: '操作成功',
      })
      cmdInfos.value.push(res.data)
    })
    .catch((error) => {
      ElMessage({
        type: 'error',
        message: error.message,
      })
    })
    addCmdDialog.value = false
  })
  .catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消',
    })
  })
}

const removeCmd = (id: number) => {
  removeCmdDao(id)
  .then(() => {
    cmdInfos.value = cmdInfos.value.filter((item: any) => item.id !== id)
  })
  .catch((err) => {
    console.log(err);
  })
}

// ===================================================
// 新增协议版本
const newVersionDialog = ref<boolean>(false)
const newVersionForm = reactive({
  versionName: '',
  isExtend: false,
  extendVersionName: '',
})
const addNewVersion = () => {
  // 继承版本问题
  const body = {
    protocol_name: props.name,
    version_name: newVersionForm.versionName,
    is_extend: newVersionForm.isExtend,
    extend_version_name: newVersionForm.extendVersionName,
  }
  console.log(body);
  
  request.post('/api/protocol/protocol_add_version/', body)
  .then((res) => {
    newVersionDialog.value = false
    console.log(res);
    
    ElMessage({
      type: 'success',
      message: '操作成功',
    })

    options.value.push({value: newVersionForm.versionName, label: newVersionForm.versionName})
    currentVersion.value = newVersionForm.versionName
    changeProtocolVersion()
  })
}

</script>

<style>
.containers {
  width: 100%;
  display: flex;
  justify-content: space-between;
  /* 使内部元素平均分布 */
  align-items: center;
  /* 垂直居中 */
  margin: auto;
}

.left {
  align-items: center;
  display: flex;

}

.right {
  display: flex;
  align-items: center;
  /* 垂直居中 */
}
.collapse1 .el-collapse-item__header {
  background-color: white; /* 设置展开区域的头部颜色 */
}
.collapse1 .el-collapse-item__wrap {
  /*border: 1px solid;*/
  /*padding: 10px;*/
  /*border-radius: 10px;*/
  margin-bottom: 8px;
  box-shadow: var(--el-box-shadow-light);
  background-color: #f9f9f9;
}
/*.collapse1 .el-collapse-item__wrap {*/
/*  background-color: white; !* 设置展开区域的背景颜色 *!*/
/*}*/
/*.collapse1 .el-collapse-item:nth-child(even) .el-collapse-item__header {*/
/*  background-color: red; !* 奇数项的背景颜色 *!*/
/*}*/
</style>
