<template>
  <div class="content" :draggable="false" v-if="group === '列表'">
    <div class="flex between">
      <div class="title">数据{{ group }}</div>
      <div class="flex between">
        <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
          <t-tooltip content="导入数据列表" placement="top">
            <div class="icon-box" @mouseenter="getDatasets()">
              <!-- <FileImportIcon /> -->
              <AddIcon />
            </div>
          </t-tooltip>

          <t-dropdown-menu>
            <t-dropdown-item :value="2" :divider="true" @click="showAddData()">
              新建变量
            </t-dropdown-item>
            <t-dropdown-item :value="1">
              <!-- <t-dropdown
                :minColumnWidth="168"
                :maxColumnWidth="300"
                :trigger="'click'"
                :hide-after-item-click="false"
               
              > -->
              我的变量列表
              <!-- </t-dropdown> -->
              <t-dropdown-menu>
                <t-dropdown-item v-if="!user.id"> 请先登录! </t-dropdown-item>
                <t-dropdown-item v-else-if="!data.datasetList.length">
                  暂无数据
                </t-dropdown-item>
                <template v-else>
                  <t-dropdown-item v-for="(dataset, i) in data.datasetList">
                    <div
                      class="hover-background item"
                      @click="onSelDataset(dataset.id)"
                    >
                      <div style="font-size: 14px">{{ dataset.name }}</div>
                      <div v-if="dataset.url" class="desc">
                        {{ dataset.url }}
                      </div>
                      <div v-else class="desc">自定义</div>
                      <!-- <t-popconfirm
                            content="确认删除吗？"
                            @confirm.stop="onDelDataset(dataset, i)"
                            @enter.stop
                            @mouseenter.stop
                          > -->
                      <span class="del" @click.stop="onDelDataset(dataset, i)">
                        <delete-icon />
                      </span>
                      <!-- </t-popconfirm> -->
                    </div>
                  </t-dropdown-item>
                </template>
              </t-dropdown-menu>
            </t-dropdown-item>

            <t-dropdown-item :value="3" :divider="true">
              在线接口

              <t-dropdown-menu
                class="menu-item-input"
                style="max-width: 216px !important"
              >
                <t-dropdown-item
                  :value="3 - 1"
                  style="max-width: 216px !important"
                >
                  <div
                    class="data-input-box"
                    style="max-width: 216px !important"
                  >
                    <t-input
                      label="地址："
                      style="width: 216px"
                      placeholder="请输入地址"
                      v-model="data.dataset.url"
                      @blur="getDatas"
                      @enter="getDatas"
                    >
                      <template #suffixIcon>
                        <CloudDownloadIcon
                          @click="getDatas"
                          :style="{ cursor: 'pointer' }"
                        />
                      </template>
                    </t-input>
                  </div>
                </t-dropdown-item>
              </t-dropdown-menu>
            </t-dropdown-item>
            <t-dropdown-item :value="2" @click="importDataset">
              从Excel导入
            </t-dropdown-item>
            <t-dropdown-item :value="4">
              <a
                :href="
                  isDownload
                    ? '/v/data.xlsx'
                    : cdn
                    ? cdn + '/v/data.xlsx'
                    : '/data.xlsx'
                "
                style="color: var(--td-text-color-primary)"
                @click.stop
              >
                下载Excel示例
              </a>
            </t-dropdown-item>
          </t-dropdown-menu>
        </t-dropdown>
        <t-dropdown :minColumnWidth="168">
          <t-tooltip content="导出数据列表" placement="top">
            <div class="icon-box">
              <!-- <FileExportIcon /> -->
              <Download1Icon />
            </div>
          </t-tooltip>
          <t-dropdown-menu>
            <t-dropdown-item @click="downloadAsJson"
              >下载为JSON</t-dropdown-item
            >
            <t-dropdown-item @click="downloadAsExcel"
              >下载为Excel</t-dropdown-item
            >
            <t-dropdown-item @click="onOkDataset()"
              >保存为我的数据列表</t-dropdown-item
            >
          </t-dropdown-menu>
        </t-dropdown>
        <t-popconfirm
          content="确认清空数据列表吗？"
          placement="bottom"
          @confirm="clearData"
        >
          <t-tooltip content="清空列表" placement="top">
            <div class="icon-box">
              <DeleteIcon />
            </div>
          </t-tooltip>
        </t-popconfirm>
        <!-- <t-tooltip content="新建变量" placement="top">
          <div class="icon-box">
            <AddIcon @click="showAddData()" />
          </div>
        </t-tooltip> -->
      </div>
    </div>
    <div class="flex between mt-8">
      <t-tooltip content="可批量导入数据图元到画布" placement="top">
        <t-checkbox v-model="data.checkAll">批量导入到画布</t-checkbox>
      </t-tooltip>
      <t-tooltip content="开启全局数据模拟" placement="top">
        <t-checkbox v-model="data.enableMock" @change="onChangeMock"
          >开启模拟</t-checkbox
        >
      </t-tooltip>
    </div>
    <div class="input-search">
      <div class="btn">
        <search-icon class="hover" />
        <!-- <img src="/img/icon_search_gray.svg" /> -->
      </div>
      <t-input
        v-model="search"
        @change="onSearch"
        @enter="onSearch"
        placeholder="搜索我的数据列表"
      />
    </div>
    <div
      id="dragElem"
      style="position: absolute; left: 0; z-index: -999"
      v-if="data.dataset?.devices?.length"
    >
      <div
        class="flex mt-4"
        v-for="(device, i) in data.dataset.devices"
        v-show="device.checked"
      >
        <div style="width: 150px; text-align: end">{{ device.label }}：</div>
        <div class="ml-4">{{ device.mock }}</div>
      </div>
    </div>
    <div
      class="mt-16 data-list"
      v-if="data.dataset?.devices?.length"
      :draggable="data.checkAll ? true : false"
      @dragstart="onAddShape($event, data.dataset?.devices)"
      @dragend="onAddShapeEnd"
    >
      <div
        v-for="(device, i) in data.dataset.devices"
        v-show="!(device.show === false)"
      >
        <div
          class="flex between data-title"
          :class="
            (device.expend ? '' : 'data-title-hover') +
            ' ' +
            (device.checked ? 'drag-checked' : '')
          "
          :draggable="data.checkAll ? false : true"
          @dragstart="onAddShape($event, device)"
          @dragend="onAddShapeEnd"
        >
          <div
            class="flex"
            style="height: 32px; line-height: 32px; cursor: pointer"
          >
            <!-- <MinusCircleIcon
              v-if="device.expend"
              @click="device.expend = false"
            />
            <AddCircleIcon v-else @click="device.expend = true" /> -->
            <t-checkbox
              v-if="data.checkAll"
              v-model="device.checked"
            ></t-checkbox>
            <template v-else>
              <CaretDownSmallIcon
                style="height: auto"
                v-if="device.expend"
                @click="device.expend = false"
              />
              <CaretRightSmallIcon
                style="height: auto"
                v-else
                @click="device.expend = true"
              />
            </template>
            <p class="title-span">{{ device.label }}</p>
          </div>

          <div class="flex">
            <t-tooltip content="开启单个模拟" placement="top">
              <div
                class="icon-box icon-item-box"
                @click="device.enableMock = !device.enableMock"
              >
                <RouterWaveIcon
                  :style="{
                    color: device.enableMock ? 'var(--color-primary)' : '',
                  }"
                />
              </div>
            </t-tooltip>
            <div class="icon-box icon-item-box" @click="showAddData(device, i)">
              <Edit2Icon />
            </div>
            <t-popconfirm content="确认删除吗？" @confirm="deleteData(i)">
              <div class="icon-box icon-item-box">
                <DeleteIcon />
              </div>
            </t-popconfirm>
          </div>
        </div>
        <div class="data-body">
          <div v-if="device.expend" class="flex">
            <span class="form-line"></span>
            <div>
              <!-- <div class="form-item form-data-item mt-8">
                <label>显示名称</label>
                <div :title="device.label">{{ device.label }}</div>
              </div> -->
              <div class="form-item form-data-item">
                <label>变量名：</label>
                <div :title="device.id">{{ device.id }}</div>
              </div>
              <div class="form-item form-data-item">
                <label>类型：</label>
                <div :title="device.type">{{ device.type }}</div>
              </div>
              <div class="form-item form-data-item">
                <label>值范围：</label>
                <div :title="device.mock">{{ device.mock }}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="flex column middle nodata" v-else>
      <img src="/img/no-data.png" />
      <div class="gray center">暂无数据</div>
      <div class="mt-20">
        <t-button theme="primary" @click="showAddData()"> 新建变量 </t-button>
      </div>
    </div>
  </div>
  <div class="content" v-if="group === '获取'">
    <div class="flex between">
      <div class="title">数据{{ group }}</div>
      <div class="flex between">
        <t-tooltip content="添加数据获取" placement="top">
          <div class="icon-box" @click="addNetwork()">
            <AddIcon />
          </div>
        </t-tooltip>
      </div>
    </div>
    <div class="input-search select-search">
      <t-select
        v-model="data.networkId"
        filterable
        clearable
        placeholder="搜索我的数据获取"
        @focus="onInputNetwork"
        :on-search="onInputNetwork"
        @change="onSelectNetWork"
      >
        <template #prefixIcon>
          <SearchIcon />
        </template>
        <t-option
          class="network-option"
          v-for="(item, i) in data.networkList"
          :key="item.id"
          :value="item.id"
          :label="item.name"
        >
          <div class="hover-background item">
            <div style="font-size: 14px">{{ item.name }}</div>
            <div class="desc">
              {{ item.url }}
            </div>
            <span class="del" @click.stop="onDelNetWork(item, i)">
              <delete-icon />
            </span>
          </div>
        </t-option>
      </t-select>
    </div>
    <div class="mt-16 data-list" v-if="data.networks.length">
      <div
        v-for="(network, i) in data.networks"
        v-show="!(network.show === false)"
      >
        <div
          class="flex between data-title"
          :class="network.expend ? '' : 'data-title-hover'"
        >
          <div style="height: 32px; line-height: 32px; cursor: pointer">
            <CaretDownSmallIcon
              style="height: auto"
              v-if="network.expend"
              @click="network.expend = false"
            />
            <CaretRightSmallIcon
              style="height: auto"
              v-else
              @click="network.expend = true"
            />
            {{ network.name }}
          </div>
          <div class="flex">
            <div class="icon-box" @click="editNetwork(network, i)">
              <Edit2Icon />
            </div>
            <t-popconfirm content="确认删除吗？" @confirm="deleteNetwork(i)">
              <div class="icon-box">
                <DeleteIcon />
              </div>
            </t-popconfirm>
          </div>
        </div>
        <div class="data-body">
          <div v-if="network.expend" class="flex">
            <span class="form-line" style="height: 88px"></span>
            <div>
              <div class="form-item form-data-item mt-8">
                <label>显示名称：</label>
                <div :title="network.name">{{ network.name }}</div>
              </div>
              <div class="form-item form-data-item mt-8">
                <label>通信方式：</label>
                <div :title="network.protocol">{{ network.protocol }}</div>
              </div>
              <div class="form-item form-data-item mt-8">
                <label>URL地址：</label>
                <div :title="network.url">{{ network.url }}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="flex column middle nodata" v-else>
      <img src="/img/no-data.png" />
      <div class="gray center">暂无数据</div>
      <div class="mt-20">
        <t-button theme="primary" @click="addNetwork()">
          添加数据获取
        </t-button>
      </div>
    </div>
  </div>
  <div class="content" v-if="group === '监听'">
    <div class="flex between">
      <div class="title">数据{{ group }}</div>
    </div>
    <div class="mt-8">
      <CodeEditor
        :key="data.randomkey"
        v-model="data.socketCbJs"
        style="min-height: 300px"
        @change="onSocketCbJsChange"
      />
      <div class="data-full-icon hover">
        <Fullscreen2Icon @click="showDataTransformation" />
      </div>
    </div>
    <div class="mt-16">
      参考文档：
      <a
        target="_blank"
        href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"
      >
        解析自定义格式数据</a
      >
    </div>
  </div>
  <!-- <div class="content" v-show="group === '数据模拟'">
    <div class="flex between">
      <div class="title">{{ group }}</div>
      <div class="flex between">
        <t-dropdown :minColumnWidth="168">
          <t-tooltip
            :content="
              data.dataset?.devices?.length
                ? '添加一条数据模拟'
                : '请先添加数据列表'
            "
            placement="top"
          >
            <div class="icon-box">
              <AddIcon />
            </div>
          </t-tooltip>
          <t-dropdown-menu v-if="data.dataset?.devices?.length">
            <t-dropdown-item >
              <div class="hover-background item" @click="onAddAllMock">导入所有数据列表</div>
            </t-dropdown-item>
            <t-dropdown-item v-for="(dataset, i) in data.dataset?.devices">
              <div class="hover-background item" @click="onAddmock(dataset)">
                <div style="font-size: 14px">{{ dataset.label }}</div>
                <div class="desc">
                  {{ dataset.id }}
                </div>
              </div>
            </t-dropdown-item>
          </t-dropdown-menu>
        </t-dropdown>
      </div>
    </div>
    <div class="mt-16 data-list data-mock-list" v-if="data.dataMocks.length">
      <div v-for="(item, i) in data.dataMocks" v-show="!(item.show === false)">
        <div
          class="flex between data-title"
          :class="item.expend ? '' : 'data-title-hover'"
        >
          <div style="height: 32px; line-height: 32px; cursor: pointer">
            <MinusCircleIcon v-if="item.expend" @click="item.expend = false" />
            <AddCircleIcon v-else @click="item.expend = true" />

            {{ item.name }}
          </div>
          <div class="flex">
            <t-popconfirm content="确认删除吗？" @confirm="deleteMock(i)">
              <div class="icon-box">
                <DeleteIcon />
              </div>
            </t-popconfirm>
          </div>
        </div>
        <div class="data-body">
          <div v-if="item.expend" class="flex">
            <span class="form-line" style="height: 150px"></span>
            <div>
              <div class="form-item form-data-item mt-8">
                <label>显示名称</label>
                <div :title="item.name">{{ item.name }}</div>
              </div>
              <div class="form-item form-data-item mt-8">
                <label>变量名</label>
                <div :title="item.id">{{ item.id }}</div>
              </div>
              <div class="form-item form-data-item form-mock-item mt-8">
                <label>模拟值
                  <t-tooltip  placement="top">
                    <template #content>
                      <div style="font-size:10px;">
                      模拟值说明<br/>
                      固定值：直接填写，例如：10<br/>
                      随机值：值1,值2,...。例如：1,2,3,4,5<br/>
                      范围数字：最小值-最大值。例如：0-1.0 或 0-100<br/>
                      随机字符串： [长度]。例如：[8]<br/>
                      </div>
                    </template>
                  <HelpCircleIcon style="font-size: 12px;"/>
                  </t-tooltip>
                </label>
                <t-input v-model="item.mock" />
              </div>
              <div class="form-item form-data-item form-mock-item mt-8">
                <label>类型</label>
                <t-select
                  class="w-full"
                  :options="typeOptions"
                  v-model="item.type"
                  placeholder="字符串"
                />
              </div>
              <div class="form-item form-swicth-item mt-8">
                <label>开启</label>
                <t-switch class="mt-8" size="small" v-model="item.enableMock" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="flex column middle nodata" v-else>
      <img src="/img/no-data.png" />
      <div class="gray center">暂无数据</div>    
    </div>
    <div class="flex between mt-24">
      <t-checkbox
        style="display: inline"
        v-model="data.enableMock"
        @change="onChangeMock"
      >
        开启模拟数据
      </t-checkbox>
    </div>
  </div> -->

  <t-dialog
    v-if="addDataDialog.show"
    :visible="true"
    class="data-dialog"
    :header="addDataDialog.header"
    @close="addDataDialog.show = false"
    @confirm="onOkAddData"
  >
    <!-- <div class="form-item mt-16">
        <label>设备</label>
        <t-input v-model="addDataDialog.data.device" placeholder="设备名称" />
      </div> -->
    <div class="form-item mt-16">
      <label>显示名称</label>
      <t-input
        @change="changeDataLabel($event)"
        :value="addDataDialog.data.label"
        placeholder="变量简短描述"
      />
    </div>
    <div class="form-item mt-16">
      <label>变量名</label>
      <t-input
        @change="changeDataID($event)"
        :value="addDataDialog.data.id"
        placeholder="变量名"
      />
    </div>
    <div class="form-item mt-16">
      <label>类型</label>
      <t-select
        class="w-full"
        :options="typeOptions"
        v-model="addDataDialog.data.type"
        placeholder="字符串"
        @change="addDataDialog.data.value = null"
      />
    </div>
    <div class="form-item mt-16">
      <label
        >值范围
        <t-tooltip content="可用做数据模拟" placement="top">
          <HelpCircleIcon style="font-size: 12px" />
        </t-tooltip>
      </label>
      <div class="w-full">
        <t-input v-model="addDataDialog.data.mock" placeholder="值范围" />
        <h6 class="desc mt-8" style="font-size: 12px">值范围说明</h6>
        <ul class="desc ml-16" style="font-size: 12px">
          <li>
            <label class="inline" style="width: 80px">固定值：</label>
            直接填写，例如：10
          </li>
          <li>
            <label class="inline" style="width: 80px">随机值：</label>
            值1,值2,...。例如：1,2,3,4,5
          </li>
          <li>
            <label class="inline" style="width: 80px">范围数字：</label>
            最小值-最大值。例如：0-1.0 或 0-100
          </li>
          <li>
            <label class="inline" style="width: 80px">随机字符串：</label>
            [长度]。例如：[8]
          </li>
        </ul>
      </div>
    </div>
  </t-dialog>
  <t-dialog
    v-if="networkDialog.show"
    :visible="true"
    width="800px"
    class="data-dialog"
    :header="networkDialog.header"
    @close="networkDialog.show = false"
    @confirm="onOkNetwork"
  >
    <template #footer>
      <div class="flex mr-8" style="justify-content: end">
        <t-checkbox v-model="networkDialog.save" class="mr-12">
          同时保存到我的数据获取
        </t-checkbox>
        <t-button @click="onOkNetwork">确定</t-button>
      </div>
    </template>
    <div style="height: 300px; padding: 8px; overflow-y: auto">
      <Network v-model="networkDialog.network" />
    </div>
  </t-dialog>
  <t-dialog
    v-if="dataTransformationDialog.show"
    :visible="true"
    header="数据监听"
    @confirm="onOkDataTransformation"
    @close="dataTransformationDialog.show = false"
    :width="800"
  >
    <CodeEditor v-model="dataTransformationDialog.data" style="height: 300px" />
    <div class="mt-8">
      参考文档：
      <a
        target="_blank"
        href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"
      >
        解析自定义格式数据</a
      >
    </div>
  </t-dialog>
</template>

<script lang="ts" setup>
import { reactive, defineComponent, ref, onMounted, toRaw } from 'vue';
import {
  FileImportIcon,
  FileExportIcon,
  DeleteIcon,
  AddIcon,
  AddCircleIcon,
  MinusCircleIcon,
  Edit2Icon,
  FileExcelIcon,
  CloudDownloadIcon,
  SearchIcon,
  Fullscreen2Icon,
  FullscreenExit1Icon,
  HelpCircleIcon,
  CaretDownSmallIcon,
  CaretRightSmallIcon,
  RouterWaveIcon,
  ArrowUpDown3Icon,
  Download1Icon
} from 'tdesign-icons-vue-next';
import { typeOptions } from '@/services/common';
import { MessagePlugin } from 'tdesign-vue-next';
import { Pen, deepClone } from '@meta2d/core';
import { useDot } from '@/services/common';
import { isDownload } from '@/services/defaults';
import { cdn } from '@/services/api';
import { importExcel, saveAsExcel } from '@/services/excel';
import axios from 'axios';
import { transformData } from '@/services/utils';
import { debounce } from '@/services/debouce';
import Network from '@/views/components/Network.vue';
import CodeEditor from '@/views/components/common/CodeEditor.vue';
import { s8 } from '@/services/random';
import { useUser } from '@/services/user';

const props = defineProps<{
  group: string;
}>();

const { user } = useUser();

const { dot, setDot } = useDot();

const data = reactive({
  //列表
  datesetBak: {},
  datasetId: '',
  networks: [],
  datasetList: [],
  dataset: {
    name: '',
    id: '',
    url: '',
    devices: [],
  } as any,
  checkAll: false,
  //获取
  networkList: [],
  input: '',
  popupVisible: false,
  networkId: '',

  //监听
  socketCbJs: '',
  full: false,

  dataMocks: [
    // {
    //   name: '',
    //   id: '',
    //   enableMock: true,
    //   mock: 'aaa',
    //   type: 'string',
    //   expend: true,
    //   show: false,
    // },
  ],
  enableMock: false,
  randomkey: s8(),
});

onMounted(() => {
  data.networks = meta2d.store.data.networks || [];
  data.dataset = (meta2d.store.data as any).dataset || {};
  data.socketCbJs = meta2d.store.data.socketCbJs || '';
  // data.dataMocks = meta2d.store.data.dataMocks || [];
  data.enableMock = meta2d.store.data.enableMock || false;
  // getNetworks();
  // getDatasets();
});

const addDataDialog = reactive<any>({});

const showAddData = (row?: any, index?: number) => {
  if (row) {
    addDataDialog.header = '编辑数据';
    addDataDialog.data = JSON.parse(JSON.stringify(row));
    addDataDialog.index = index;
  } else {
    addDataDialog.header = '添加数据';
    addDataDialog.data = { type: 'string', expend: true };
  }

  addDataDialog.show = true;
};

const deleteData = (row: any) => {
  data.dataset.devices.splice(row, 1);
  (meta2d.store.data as any).dataset = data.dataset;
  setDot(true);
};

const clearData = () => {
  data.datasetId = undefined;
  data.dataset.id = undefined;
  data.dataset.name = undefined;
  data.dataset.url = undefined;
  data.dataset.devices = [];
  setDot(true);
};

const changeDataLabel = (value) => {
  if (!value) {
    MessagePlugin.error('显示名称不能为空！');
    return;
  }
  let item = data.dataset.devices?.filter((item) => item.label === value);
  if (item && item.length) {
    MessagePlugin.error('显示名称重复！');
    return;
  }
  addDataDialog.data.label = value;
};

const changeDataID = (value) => {
  if (!value) {
    MessagePlugin.error('变量名不能为空！');
    return;
  }
  let item = data.dataset.devices?.filter((item) => item.id === value);
  if (item && item.length) {
    MessagePlugin.error('变量名重复！');
    return;
  }
  addDataDialog.data.id = value;
};

const onOkAddData = () => {
  if (!addDataDialog.data.label) {
    MessagePlugin.error('请填写名称');
    return;
  }
  if (!addDataDialog.data.id) {
    MessagePlugin.error('请填写数据ID');
    return;
  }
  if (!data.dataset.devices) {
    data.dataset.devices = [];
  }
  if (addDataDialog.header === '添加数据') {
    data.dataset.devices.push(addDataDialog.data);
  } else {
    data.dataset.devices[addDataDialog.index] = addDataDialog.data;

    //更新所有绑定该id的pen label
    let binds = meta2d.store.bind[addDataDialog.data.id];
    if (binds) {
      binds.forEach((item) => {
        const pen: Pen = meta2d.findOne(item.id);
        pen.realTimes &&
          pen.realTimes.forEach((_realTime) => {
            if (_realTime.key === item.key) {
              _realTime.bind.label = addDataDialog.data.label;
            }
          });
      });
    }
  }
  (meta2d.store.data as any).dataset = data.dataset;
  addDataDialog.show = false;
};

const importDataset = async () => {
  let columns: any = [
    {
      header: '设备',
      key: 'device',
    },
    {
      header: '显示名称',
      key: 'label',
    },
    {
      header: '变量名',
      key: 'id',
    },
    {
      header: '类型',
      key: 'type',
    },
    {
      header: '值范围',
      key: 'mock',
    },
  ];
  const _data: any = await importExcel(columns);
  _data.forEach((item) => {
    if (item.device) {
      item.label = item.device + '-' + item.label;
      delete item.device;
    }
  });
  mergeDataset(data.dataset, _data);
  (meta2d.store.data as any).dataset = data.dataset;
};

const downloadAsExcel = () => {
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error('变量列表不能为空！');
    return;
  }
  const name = meta2d.store.data.name;
  const columns: any[] = [
    {
      key: 'label',
      header: '显示名称',
    },
    {
      key: 'id',
      header: '变量名',
    },
    {
      key: 'type',
      header: '类型',
    },
    {
      key: 'mock',
      header: '值范围',
    },
  ];
  saveAsExcel(name, columns, data.dataset.devices);
};

const downloadAsJson = () => {
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error('变量列表不能为空！');
    return;
  }
  import('file-saver').then(({ saveAs }) => {
    saveAs(
      new Blob([JSON.stringify(data.dataset)], {
        type: 'text/plain;charset=utf-8',
      }),
      `${data.dataset.name || '未命名'}.json`
    );
  });
};

const onOkDataset = async (saveas = false) => {
  // if (!dataDialog.dataset.name) {
  //   MessagePlugin.error('名称不能为空');
  //   return;
  // }
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error('变量列表不能为空');
    return;
  }
  const dataset = JSON.parse(JSON.stringify(data.dataset));
  let _data = dataset;
  _data.type = 'dataset';
  if (!_data.name) {
    _data.name = meta2d.store.data.name;
  }
  _data = transformData(dataset, 'toNetwork');
  // 保存到我的数据源
  if (saveas || !dataset.id) {
    delete dataset.id;
    delete dataset._id;
    dataset.type = 'dataset';
    const ret: any = await axios.post(`/api/data/datasource/add`, _data);
    if (!ret) {
      return;
    }
    ret.id = ret.id || ret._id;
    data.datasetId = ret.id;
    dataset.id = ret.id;
    data.dataset.id = ret.id;
    data.datasetList.push(dataset);
  } else {
    const ret: any = await axios.post(`/api/data/datasource/update`, _data);
    if (!ret) {
      return;
    }
    data.datasetList.forEach((item: any, index: number) => {
      if (
        item.id === dataset.id ||
        (item._id === dataset._id && dataset._id != undefined)
      ) {
        data.datasetList.splice(index, 1, dataset);
      }
    });
  }
  delete dataset.devices;
  // @ts-ignore
  // console.log("dataset",dataset);
  // meta2d.store.data.dataset = dataset;

  // setDot(true);

  data.editDataset = false;
  delete data.datesetBak;
};

const mergeDataset = (arr1: any, arr2: any[]) => {
  if (!(arr2 && arr2.length)) {
    return;
  }
  if (!arr1.devices) {
    arr1.devices = [];
  }
  arr2.forEach((item) => {
    let index = arr1.devices.findIndex((elem) => elem.id === item.id);
    if (index >= 0) {
      Object.assign(arr1.devices[index], item);
    } else {
      arr1.devices.push(item);
    }
  });
};

const getDatas = async () => {
  if (!data.dataset.url) {
    return;
  }
  const ret = await axios.get(data.dataset.url);
  let flattenRet = flattenTree(ret);
  if (flattenRet) {
    mergeDataset(data.dataset, flattenRet);
    (meta2d.store.data as any).dataset = data.dataset;
  }
};

//展开树
const flattenTree = (root) => {
  if (!root) return []; // 空树返回空数组

  const result = []; // 存储展开后的数组

  // 递归遍历树
  function dfs(node) {
    result.push({
      id: node.id,
      label: node.label || node.name,
      device: node.device || node.id,
      type: node.type,
      mock: node.mock,
      // children: node.children,
    }); // 将当前节点值添加到结果数组
    // 遍历当前节点的子节点
    if (node.children) {
      for (let child of node.children) {
        dfs(child); // 递归调用DFS
      }
    }
  }
  root.forEach((item) => {
    dfs(item);
  });
  // dfs(root); // 从根节点开始遍历

  return result;
};

const onSelDataset = async (datasetId = false) => {
  if (datasetId) {
    const dataset = data.datasetList.find((item: any) => {
      return item.id === datasetId;
    });

    if (!dataset) {
      return;
    }

    if (dataset.url) {
      const ret = await axios.get(dataset.url);
      if (ret) {
        dataset.devices = ret;
      }
    } else {
      const ret = await axios.post(`/api/data/datasource/get`, {
        id: dataset.id,
      });
      if (ret?.data) {
        Object.assign(dataset, { ...ret.data });
      }
    }
    mergeDataset(data.dataset, dataset.devices);

    (meta2d.store.data as any).dataset = data.dataset;
    // dataDialog.dataset = dataset;

    // if (!init) {
    //   const d = JSON.parse(JSON.stringify(dataset));
    //   delete d.devices;
    //   // @ts-ignore
    //   meta2d.store.data.dataset = d;

    //   setDot(true);
    // }
  }
};

// 请求我的数据模型
const getDatasets = async (name?: string) => {
  // console.log("进入")
  if (!user.id) {
    MessagePlugin.error('请先登录');
    return;
  }
  const body: any = {
    type: 'dataset',
    projection: 'id,data,name,type',
  };
  if (name) {
    body.name = name;
  }
  const ret: any = await axios.post(`/api/data/datasource/list`, body, {
    params: {
      current: 1,
      pageSize: 10,
    },
  });
  if (ret?.list) {
    const list = [];
    let found = false;
    for (const item of ret.list) {
      item.id = item.id || item._id;
      list.push(transformData(item, 'toMetaNetwork'));
      if (data.dataset?.id === item.id) {
        found = true;
      }
    }
    if (data.dataset?.id && !found) {
      list.push(data.dataset);
    }

    data.datasetList = list;
  }
};

const onDelDataset = async (item: any, i: number) => {
  const ret: any = await axios.post(`/api/data/datasource/delete`, {
    id: item.id,
  });
  if (
    (meta2d.store.data as any).dataset &&
    (meta2d.store.data as any).dataset.id === item.id
  ) {
    //@ts-ignore
    meta2d.store.data.dataset = {};
    data.dataset = {};
    data.datasetId = undefined;
  }
  if (ret) {
    data.datasetList.splice(i, 1);
  }
};

const search = ref('');
const onSearch = () => {
  // if (!search.value) {
  //   return;
  // }
  data.dataset.devices.forEach((item) => {
    if (
      item.label.indexOf(search.value) !== -1 ||
      item.id.indexOf(search.value) !== -1
    ) {
      item.show = true;
    } else {
      item.show = false;
    }
  });
};

const onInputNetwork = (e) => {
  debounce(getNetworks, 300, e);
};

const onSelectNetWork = (value) => {
  if (!value) {
    return;
  }
  const network: any = data.networks.find((elem: any) => value === elem.id);
  if (!network) {
    const item = data.networkList.find((elem: any) => value === elem.id);
    data.networks.push(item);
    meta2d.store.data.networks = toRaw(data.networks);
    meta2d.connectNetwork();
    setDot(true);
  }
  // data.input = null;
  data.popupVisible = false;
};

// 请求我的实时数据
const getNetworks = async (e?) => {
  const ret: any = await axios.post(
    `/api/data/datasource/list`,
    {
      // q: {
      name: e,
      // },
      type: 'subscribe',
      projection: 'id,data,name,type',
    },
    {
      params: {
        current: 1,
        pageSize: 10,
      },
    }
  );
  if (ret?.list) {
    const list = [];
    for (const item of ret.list) {
      item.id = item.id || item._id;
      list.push(transformData(item, 'toMetaNetwork'));
    }
    data.networkList = list;
  }
};

const onDelNetWork = async (item: any, i: number) => {
  const ret: any = await axios.post(`/api/data/datasource/delete`, {
    id: item.id || item._id,
  });
  if (ret) {
    data.networkList.splice(i, 1);
  }
};

const deleteNetwork = (index: number) => {
  data.networks.splice(index, 1);
  meta2d.store.data.networks = toRaw(data.networks);
  meta2d.connectNetwork();
  setDot(true);
};

const networkDialog = reactive<any>({
  save: true,
});
const editNetwork = (network: any, index: number) => {
  networkDialog.network = JSON.parse(JSON.stringify(network));
  networkDialog.editNetwork = 2;
  networkDialog.editNetworkIndex = index;
  networkDialog.header = '编辑数据获取';
  networkDialog.show = true;
};

const addNetwork = () => {
  networkDialog.network = {
    name: '',
    type: 'subscribe',
    protocol: 'mqtt',
    url: '',
    options: {
      clientId: '',
      username: '',
      password: '',
      customClientId: false,
    },
  };
  networkDialog.editNetwork = 1;
  networkDialog.header = '添加数据获取';
  networkDialog.show = true;
};

const onOkNetwork = async () => {
  const _data = transformData(networkDialog.network, 'toNetwork');
  if (networkDialog.editNetwork === 1) {
    if (!networkDialog.network.url) {
      MessagePlugin.error('URL地址不能为空！');
      return;
    }
    if (!networkDialog.network.name) {
      MessagePlugin.error('名称不能为空！');
      return;
    }
    if (networkDialog.save) {
      const ret: any = await axios.post(`/api/data/datasource/add`, _data);
      if (!ret) {
        return;
      }
      ret.id = ret.id || ret._id;
      networkDialog.network.id = ret.id;
    }
    data.networks.push(networkDialog.network);
    data.networkList.push(networkDialog.network);
  } else if (networkDialog.editNetwork === 2) {
    if (networkDialog.save) {
      const ret: any = await axios.post(`/api/data/datasource/update`, _data);
      if (!ret) {
        return;
      }
    }
    //替换
    let index = networkDialog.editNetworkIndex;
    if (index !== undefined) {
      data.networks.splice(index, 1, networkDialog.network);
    }
  }
  networkDialog.show = false;
  networkDialog.editNetwork = 0;
  meta2d.store.data.networks = toRaw(data.networks);
  meta2d.connectNetwork();
  setDot(true);
};

const dataTransformationDialog = reactive<any>({
  show: false,
  data: '',
});

const showDataTransformation = () => {
  dataTransformationDialog.data = meta2d.store.data.socketCbJs;
  dataTransformationDialog.show = true;
};

const onOkDataTransformation = () => {
  meta2d.store.data.socketCbJs = dataTransformationDialog.data;
  data.randomkey = s8();
  data.socketCbJs = dataTransformationDialog.data;
  meta2d.listenSocket();
  dataTransformationDialog.show = false;
};

let timer: any = 0;

const onSocketCbJsChange = (e) => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    meta2d.store.data.socketCbJs = data.socketCbJs;
    meta2d.listenSocket();
  }, 3000);
};

const onChangeMock = () => {
  // @ts-ignore
  meta2d.store.data.enableMock = data.enableMock;
  if (data.enableMock) {
    meta2d.startDataMock();
  } else {
    meta2d.stopDataMock();
  }
};

const onAddShape = (e, _data) => {
  e.stopPropagation();
  let data: any;
  if (Array.isArray(_data)) {
    const dragElem = document.getElementById('dragElem');
    let width = dragElem.offsetWidth;
    e.dataTransfer.setDragImage(dragElem, width / 2, 10);
    const checked = _data.filter((item) => item.checked);
    if(!checked.length){
      MessagePlugin.error('请先选择数据');
      return;
    }
    data = [];
    checked.forEach((item) => {
      data.push(
        ...[
          {
            text: item.label + ':',
            width: 150,
            height: 20,
            name: 'text',
            dataset: true,
            textAlign: 'right',
          },
          {
            text: item.mock,
            width: 100,
            height: 20,
            name: 'text',
            dataset: true,
            textAlign: 'left',
            realTimes: [
              {
                label: '文字',
                key: 'text',
                type: 'string',
                bind: deepClone(item),
              },
            ],
          },
        ]
      );
    });
  } else {
    data = [
      {
        text: _data.label + ':',
        width: 150,
        height: 20,
        name: 'text',
        dataset: true,
        textAlign: 'right',
      },
      {
        text: _data.mock,
        width: 100,
        height: 20,
        name: 'text',
        dataset: true,
        textAlign: 'left',
        realTimes: [
          {
            label: '文字',
            key: 'text',
            type: 'string',
            bind: deepClone(_data),
          },
        ],
      },
    ];
  }
  meta2d.canvas.addCaches = deepClone(data);
};

const onAddShapeEnd = () => {
  setTimeout(()=>{
    meta2d.initBinds();
  },1000);
}

const onAddmock = (item: any) => {
  if (data.dataMocks.find((elem) => elem.id === item.id)) {
    return;
  }
  item.name = item.label;
  data.dataMocks.push(deepClone(item));
  (meta2d.store.data as any).dataMocks = data.dataMocks;
  meta2d.startDataMock();
};

const onAddAllMock = () => {
  if (!data.dataset.devices) {
    return;
  }
  data.dataset.devices.forEach((item) => {
    if (data.dataMocks.find((elem) => elem.id === item.id)) {
      return;
    }
    item.name = item.label;
    data.dataMocks.push(deepClone(item));
  });
  (meta2d.store.data as any).dataMocks = data.dataMocks;
  meta2d.startDataMock();
};

const deleteMock = (index: number) => {
  data.dataMocks.splice(index, 1);
  (meta2d.store.data as any).dataMocks = data.dataMocks;
  setDot(true);
};
</script>
<style lang="postcss" scoped>
/* :deep(.data-input-box){
  position: absolute;
    left: 193px;
    width: 501px;
    top: 80px;
} */
.content {
  background: var(--color-background-active);
  padding: 16px;

  .input-search {
    flex-shrink: 0;
    color: #878f9c;
    padding: 0px;
    margin-top: 10px;

    .btn {
      background: #fff0;
      left: 12px;

      img {
        background-color: #fff0;
        margin-top: 9px;
      }
    }

    :deep(.t-select) {
      .t-input {
        padding-left: 8px !important;
      }
    }
  }

  .select-search {
    .t-input {
      padding-left: 8px !important;

      .t-icon {
        font-size: 12px;
      }
    }
  }

  .title {
    height: 32px;
    line-height: 32px;
  }

  .title-span {
    display: inline-block;
    margin-left: 4px;
    max-width: 108px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .data-list {
    /* padding: 12px 6px; */
    /* background: var(--color-background-active); */
    max-height: calc(100vh - 200px);
    margin-bottom: 24px;
    overflow-y: auto;

    .data-title {
      /* padding: 4px; */
    }

    .data-body {
      margin-bottom: 8px;
    }

    .data-title-hover {
      &:hover {
        background: var(--color-background-input);
        border-radius: 4px;
      }
    }

    width: 234px;

    & > div {
      width: 218px;
    }
  }

  .data-mock-list {
    height: auto;
    max-height: calc(100vh - 220px);
  }

  .icon-box {
    width: 24px;
    height: 24px;
    margin: 4px;
    text-align: center;
    line-height: 24px;
    border-radius: 4px;

    &:hover {
      background: var(--td-brand-color-light);
    }

    .t-icon {
      width: 14px;
      height: 14px;
    }
  }

  .icon-item-box {
    height: 30px;
    line-height: 30px;
    margin: 1px;
  }

  .nodata {
    padding-top: 80px;

    img {
      width: 80px;
    }

    .gray {
      margin-top: 8px;
    }

    .t-button {
      //width: 64px;
      height: 24px;
      padding-left: 8px;
      padding-right: 8px;
    }
  }

  .form-line {
    margin-left: 12px;
    width: 11px;
    /* height: 120px; */
    /* border-bottom: 1px solid var(--color-background-input); */
    /* border-left: 1px solid var(--color-background-input); */
  }

  .form-data-item {
    margin-left: 4px;
    margin-top: 4px;

    /* margin-right: 12px; */
    label {
      /* color: #ffffff80; */
      height: 24px;
      line-height: 24px;
      width: 60px;
    }

    & > div {
      width: 118px;
      height: 24px;
      line-height: 24px;
      /* background: var(--color-background-input); */
      border-radius: 4px;
      /* color: #e3e8f459; */
      padding-left: 8px;
      padding-right: 8px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }

  .form-mock-item {
    & > div {
      padding: 0px;

      :deep(.t-input) {
        height: 24px !important;
        border: 0px;
      }
    }
  }

  .form-swicth-item {
    margin-left: 4px;

    label {
      /* color: #ffffff80; */
      height: 24px;
      width: 56px;
    }
  }

  .data-code {
    width: 218px;

    .code-editor {
      height: 126px;
    }
  }

  .data-code-full {
    position: absolute;
    /* right: calc(50% - 250px); */
    width: 100%;
    height: 100vh;
    background: var(--td-mask-active);
    right: 0px;
    top: 0px;

    .code-editor {
      width: 800px;
      margin: 0 auto;
      height: 80%;
      margin-top: 16vh;
    }

    .data-full-icon {
      .t-icon {
        margin-right: calc(50% - 384px);
      }
    }
  }

  .data-full-icon {
    margin-top: -20px;
    /* z-index: 10000; */
    position: relative;
    display: flex;
    justify-content: flex-end;
    width: 100%;

    .t-icon {
      margin-right: 16px;
      cursor: pointer;
      height: 16px;
      width: 16px;
    }
  }

  ul {
    list-style-type: none;
  }
}
</style>
<style lang="postcss">
.menu-item-a {
  &:hover {
    color: var(--td-brand-color);
  }
}

.network-option {
  height: 100%;
  padding: 0px;
}
</style>
