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

          <t-dropdown-menu>
            <t-dropdown-item :value="2" :divider="true" @click="showAddData()">
              {{$t('新建属性')}}
            </t-dropdown-item>
            <t-dropdown-item :value="1">
              {{$t('我的属性列表')}}
              <!-- </t-dropdown> -->
              <t-dropdown-menu>
                <t-dropdown-item v-if="!user.id"> {{$t('请先登录')}}! </t-dropdown-item>
                <t-dropdown-item v-else-if="!data.datasetList.length">
                  {{$t('暂无数据')}}
                </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">{{$t('自定义')}}</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('在线接口')}}

              <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="$t('地址：')"
                      style="width: 216px"
                      :placeholder="$t('请输入地址')"
                      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">
              {{$t( '从Excel导入' )}}
            </t-dropdown-item>
            <t-dropdown-item :value="4">
              <a
                :href="cdn
                    ? cdn + '/v/data.xlsx'
                    : '/data.xlsx'
                "
                style="color: var(--td-text-color-primary)"
                @click.stop
              >
               {{$t( '下载Excel示例' )}}
              </a>
            </t-dropdown-item>
          </t-dropdown-menu>
        </t-dropdown>
        <t-dropdown :minColumnWidth="168">
          <t-tooltip placement="top" :content="$t('导出属性列表')">
            <div class="icon-box">
              <!-- <FileExportIcon /> -->
              <Download1Icon />
            </div>
          </t-tooltip>
          <t-dropdown-menu>
            <t-dropdown-item @click="downloadAsJson"
              >{{$t( '下载为JSON' )}}</t-dropdown-item
            >
            <t-dropdown-item @click="downloadAsExcel"
              >{{$t( '下载为Excel' )}}</t-dropdown-item
            >
            <t-dropdown-item @click="onOkDataset()"
              >{{$t( '保存为我的属性列表' )}}</t-dropdown-item
            >
          </t-dropdown-menu>
        </t-dropdown>
        <t-popconfirm placement="bottom" @confirm="clearData" :content="$t('确认清空属性列表吗？')">
          <t-tooltip placement="top" :content="$t('清空列表')">
            <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 placement="top" :content="$t('可批量导入数据图元到画布')">
        <t-checkbox v-model="data.checkAll" @change="onCheckAllChange">{{$t('批量导入到画布')}}</t-checkbox>
      </t-tooltip>
      <t-tooltip placement="top" :content="$t('开启全局数据模拟')">
        <t-checkbox v-model="data.enableMock" @change="onChangeMock">{{$t('开启')}}</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="$t('搜索我的属性列表')"></t-input>
    </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"
              @click="onCheckChange($event,i)"
            ></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" @click="checkChange($event,device,i)">{{ device.label }}</p>
          </div>

          <div class="flex">
            <t-tooltip :content="$t('开启单个模拟')" 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 @confirm="deleteData(i)" :content="$t('确认删除吗？')">
              <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>{{$t('属性名')}}：</label>
                <div :title="device.id">{{ device.id }}</div>
              </div>
              <div class="form-item form-data-item">
                <label>{{$t('类型')}}：</label>
                <div :title="device.type">{{ device.type }}</div>
              </div>
              <div class="form-item form-data-item">
                <label>{{$t('值范围')}}：</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">{{$t( '暂无数据' )}}</div>
      <div class="mt-20">
        <t-button theme="primary" @click="showAddData()"> {{$t('新建属性')}} </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 placement="top" :content="$t('添加数据源')">
          <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="$t('搜索我的数据源')"
        @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 @confirm="deleteNetwork(i)" :content="$t('确认删除吗？')">
              <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>{{$t('显示名称')}}：</label>
                <div :title="network.name">{{ network.name }}</div>
              </div>
              <div class="form-item form-data-item mt-8">
                <label>{{$t('通信方式')}}：</label>
                <div :title="network.protocol">{{ network.protocol }}</div>
              </div>
              <div class="form-item form-data-item mt-8">
                <label>URL{{$t('地址')}}：</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">{{$t( '暂无数据' )}}</div>
      <div class="mt-20">
        <t-button theme="primary" @click="addNetwork()">
          {{$t('添加数据源')}}
        </t-button>
      </div>
    </div>
  </div>
  <div class="content" v-if="group === $t('解析')">
    <div class="flex between">
      <div class="title">{{$t('数据')}}{{ 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">
      {{$t('参考文档')}}：
      <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">
        {{$t('解析自定义格式数据')}}</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>{{$t('显示名称')}}</label>
      <t-input @change="changeDataLabel($event)" :value="addDataDialog.data.label" :placeholder="$t('属性简短描述')"></t-input>
    </div>
    <div class="form-item mt-16">
      <label>{{$t('属性名')}}</label>
      <t-input @change="changeDataID($event)" :value="addDataDialog.data.id" :placeholder="$t('属性名')"></t-input>
    </div>
    <div class="form-item mt-16">
      <label>{{$t('类型')}}</label>
      <t-select class="w-full" :options="typeOptions" v-model="addDataDialog.data.type" @change="addDataDialog.data.value = null" :placeholder="$t('字符串')"></t-select>
    </div>
    <div class="form-item mt-16">
      <label>{{$t('值范围')}}
        <t-tooltip placement="top" :content="$t('可用做数据模拟')">
          <HelpCircleIcon style="font-size: 12px"></HelpCircleIcon>
        </t-tooltip>
      </label>
      <div class="w-full">
        <t-input v-model="addDataDialog.data.mock" :placeholder="$t('值范围')"></t-input>
        <h6 class="desc mt-8" style="font-size: 12px">{{$t('值范围说明')}}</h6>
        <ul class="desc ml-16" style="font-size: 12px">
          <li>
            <label class="inline" style="width: 80px">{{$t('固定值')}}：</label>
            {{$t('直接填写')}}，{{$t('例如')}}：10
          </li>
          <li>
            <label class="inline" style="width: 80px">{{$t('随机值')}}：</label>
            {{$t('值')}}1,{{$t('值')}}2,...。{{$t('例如')}}：1,2,3,4,5
          </li>
          <li>
            <label class="inline" style="width: 80px">{{$t('范围数字')}}：</label>
            {{$t('最小值')}}-{{$t('最大值')}}。{{$t('例如')}}：0-1.0 {{$t('或')}} 0-100
          </li>
          <li>
            <label class="inline" style="width: 80px">{{$t('随机字符串')}}：</label>
            [{{$t('长度')}}]。{{$t('例如')}}：[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('同时保存到我的数据源')}}
        </t-checkbox>
        <t-button @click="onOkNetwork">{{$t('确定')}}</t-button>
      </div>
    </template>
    <div style="max-height: 450px; padding: 8px; overflow-y: auto">
      <Network v-model="networkDialog.network" />
    </div>
  </t-dialog>
  <t-dialog
    v-if="dataTransformationDialog.show"
    :visible="true"
    :header="$t('数据监听')"
    @confirm="onOkDataTransformation"
    @close="dataTransformationDialog.show = false"
    :width="800"
  >
    <CodeEditor v-model="dataTransformationDialog.data" style="height: 300px" />
    <div class="mt-8">
      {{$t('参考文档')}}：
      <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">
        {{$t('解析自定义格式数据')}}</a>
    </div>
  </t-dialog>
</template>

<script lang="ts" setup>
import { reactive, defineComponent, ref, onMounted, toRaw, watch, getCurrentInstance } 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 { 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 { proxy } = getCurrentInstance();
const $t = proxy.$t
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();
  if(!search.value){
    onSearch();
  }
});

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

const showAddData = (row?: any, index?: number) => {
  if (row) {
    addDataDialog.header = $t('编辑数据');
    addDataDialog.data = JSON.parse(JSON.stringify(row));
    addDataDialog.index = index;
  } else {
    addDataDialog.header = $t('添加数据');
    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($t('显示名称不能为空！'));
    return;
  }
  let item = data.dataset.devices?.filter((item) => item.label === value);
  if (item && item.length) {
    MessagePlugin.error($t('显示名称重复！'));
    return;
  }
  addDataDialog.data.label = value;
};

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

const onOkAddData = () => {
  if (!addDataDialog.data.label) {
    MessagePlugin.error($t('请填写名称'));
    return;
  }
  if (!addDataDialog.data.id) {
    MessagePlugin.error($t('请填写数据ID'));
    return;
  }
  if (!data.dataset.devices) {
    data.dataset.devices = [];
  }
  if (addDataDialog.header === $t('添加数据')) {
    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: $t('设备'),
      key: 'device',
    },
    {
      header: $t('显示名称'),
      key: 'label',
    },
    {
      header: $t('属性名'),
      key: 'id',
    },
    {
      header: $t('类型'),
      key: 'type',
    },
    {
      header: $t('值范围'),
      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($t('属性列表不能为空！'));
    return;
  }
  const name = meta2d.store.data.name;
  const columns: any[] = [
    {
      key: 'label',
      header: $t('显示名称'),
    },
    {
      key: 'id',
      header: $t('属性名'),
    },
    {
      key: 'type',
      header: $t('类型'),
    },
    {
      key: 'mock',
      header: $t('值范围'),
    },
  ];
  saveAsExcel(name, columns, data.dataset.devices);
};

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

const onOkDataset = async (saveas = false) => {
  // if (!dataDialog.dataset.name) {
  //   MessagePlugin.error($t('名称不能为空'));
  //   return;
  // }
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error($t('属性列表不能为空'));
    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($t("进入"))
  if (!user.id) {
    MessagePlugin.error($t('请先登录'));
    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 = $t('编辑数据源');
  networkDialog.show = true;
};

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

const onOkNetwork = async () => {
  const _data = transformData(networkDialog.network, 'toNetwork');
  if (networkDialog.editNetwork === 1) {
    if (['mqtt','websocket','http'].includes(networkDialog.network.protocol)&& !networkDialog.network.url) {
      MessagePlugin.error($t('URL地址不能为空！'));
      return;
    }
    if (!networkDialog.network.name) {
      MessagePlugin.error($t('名称不能为空！'));
      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 onCheckAllChange = (e) => {
  if(!e){
    data.dataset?.devices?.forEach((item) => {
      item.checked = false;
    });
  }
}

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($t('请先选择数据'));
      return;
    }
    data = [];
    checked.forEach((item) => {
      if(globalThis.style1){
        data.push(
        ...[
          {
            text: item.label,
            width: 150,
            height: 20,
            name: 'text',
            dataset: true,
            textAlign: 'right',
          },
          {
            text: item.mock||0,
            width: 58,
            height: 28,
            name: 'rectangle',
            dataset: true,
            // textAlign: 'left',
            color:"#478BFFFF",
            textColor: "#A9C9FFFF",
            background: "#478BFF1F",
            fontWeight: "bold",
            borderRadius:0.1,
            lineWidth:1,
            realTimes: [
              {
                label: $t('文字'),
                key: 'text',
                type: 'string',
                bind: deepClone(item),
              },
            ],
          },
        ]
      );
      }else{
      data.push(
        ...[
          {
            text: item.label + ':',
            width: 150,
            height: 28,
            name: 'text',
            dataset: true,
            textAlign: 'right',
          },
          {
            text: item.mock,
            width: 58,
            height: 20,
            name: 'text',
            dataset: true,
            textAlign: 'left',
            realTimes: [
              {
                label: $t('文字'),
                key: 'text',
                type: 'string',
                bind: deepClone(item),
              },
            ],
          },
        ]
      );
        }
    });
  } else {
    if(globalThis.style1){
      data = [
      {
        text: _data.label,
        width: 150,
        height: 28,
        name: 'text',
        dataset: true,
        textAlign: 'right',
      },
      {
        text: _data.mock||0,
        width: 58,
        height: 28,
        name: 'rectangle',
        dataset: true,
        // textAlign: 'left',
        color:"#478BFFFF",
        textColor: "#A9C9FFFF",
        background: "#478BFF1F",
        fontWeight: "bold",
        borderRadius:0.1,
        lineWidth:1,
        realTimes: [
          {
            label: $t('文字'),
            key: 'text',
            type: 'string',
            bind: deepClone(_data),
          },
        ],
      },
    ];
    }else{
    data = [
      {
        text: _data.label + ':',
        width: 150,
        height: 20,
        name: 'text',
        dataset: true,
        textAlign: 'right',
      },
      {
        text: _data.mock,
        width: 58,
        height: 20,
        name: 'text',
        dataset: true,
        textAlign: 'left',
        realTimes: [
          {
            label: $t('文字'),
            key: 'text',
            type: 'string',
            bind: deepClone(_data),
          },
        ],
      },
    ];
    }
  }
  meta2d.canvas.addCaches = deepClone(data);
};

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

let lastIndex = -1;

const onCheckChange = (e,i) => {
  if( lastIndex>-1 ){
    if(e.shiftKey){
      let start = Math.min(i,lastIndex);
      let end = Math.max(i,lastIndex);
      data.dataset?.devices?.forEach((item,index) => {
        if(index>=start && index<=end){
          item.checked = true;
        }
      });
      e.stopPropagation();
      e.preventDefault();
    }
  }
  lastIndex = i;

}

const checkChange = (e, device, i) => {
  data.checkAll&&(device.checked = !device.checked);
  if( lastIndex>-1 ){
    if(e.shiftKey){
      let start = Math.min(i,lastIndex);
      let end = Math.max(i,lastIndex);
      data.dataset?.devices?.forEach((item,index) => {
        if(index>=start && index<=end){
          item.checked = true;
        }
      });
    }
  }
  lastIndex = i;
}

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>
