<!-- 
 * @Description: 监控管理
 * @Author: wangwenpei
 * @Date: 2024-07-18 15:44:05
!-->
<template>
  <div class="main-box">
    <div class="card treeBox">
      <p class="title">摄像头分组管理</p>
      <div class="btn">
        <el-button icon="CirclePlus" @click="append('add', {})" type="primary">添加分组</el-button>
      </div>
      <div class="treeContent">
        <el-input clearable v-model="filterText" style="width: 100%" placeholder="请输入关键字" />
        <el-tree
          style="max-width: 600px"
          ref="treeRef"
          :data="treeData"
          node-key="id"
          default-expand-all
          :props="defaultProps"
          :expand-on-click-node="false"
          :check-on-click-node="true"
          :highlight-current="true"
          :filter-node-method="filterNode"
          :current-node-key="defaultHighlightKey"
          @node-click="handleNodeClick"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <span class="node-label" :title="node.label">{{ node.label }}</span>
              <span v-if="data.id && data.id != '-1'">
                <el-icon size="16" title="添加分组" @click.stop="append('addChild', data)"><CirclePlus /></el-icon>
                <el-icon size="16" title="编辑分组" @click.stop="append('edit', data)" style="margin-left: 8px"><Edit /></el-icon>
                <el-icon size="16" title="设置推送人" @click.stop="pushPerson(FormOptEnum.GroupPushPerson, data)" style="margin-left: 8px"
                  ><UserFilled
                /></el-icon>
                <el-icon size="16" title="删除分组" @click.stop="remove(data.id, '删除该分组')" style="margin-left: 8px"><Delete /></el-icon>
              </span>
            </span>
          </template>
        </el-tree>
      </div>
    </div>
    <div class="table-box">
      <ProTable ref="proTable" title="视频列表" :columns="columns" :request-api="monitorLIVEApi.list">
        <!-- 表格 header 按钮 -->
        <template #tableHeader="scope">
          <s-button v-auth="monitorLiveButtonCode.add" suffix="摄像头" @click="onOpen(FormOptEnum.ADD)" />
          <s-button
            type="danger"
            plain
            suffix="摄像头"
            :opt="FormOptEnum.DELETE"
            :disabled="!scope.isSelected"
            @click="onDelete(scope.selectedListIds, '删除所选数据')"
          />
          <el-button :disabled="!scope.isSelected" plain @click="omMove(FormOptEnum.ADD, scope.selectedListIds)" type="success">移动至分组</el-button>
        </template>
        <!-- 表格 菜单类型 按钮 -->
        <!-- 操作 -->
        <template #operation="scope">
          <el-space>
            <s-button link :opt="FormOptEnum.EDIT" @click="onOpen(FormOptEnum.EDIT, scope.row)">编辑</s-button>
            <s-button link :opt="FormOptEnum.VIEW" @click="onDetail(scope.row)"> 查看 </s-button>
            <!-- <s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.id], `确定删除该摄像头吗？`)" />
          <s-button link :opt="FormOptEnum.VIEW" @click="pushPerson(FormOptEnum.VideoPushPerson, scope.row)"> 推送人 </s-button> -->
            <el-dropdown @command="handleCommand">
              <el-link type="primary" :underline="false" :icon="ArrowDown"> 更多 </el-link>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item :command="command(scope.row, cmdEnum.Delete)">
                    {{ cmdEnum.Delete }}
                  </el-dropdown-item>
                  <el-dropdown-item :command="command(scope.row, cmdEnum.pushPerson)">
                    {{ cmdEnum.pushPerson }}
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </el-space>
        </template>
      </ProTable>
      <!-- 添加分组弹框 -->
      <el-dialog v-model="groupVisible" :title="groupTitle" width="600px" :before-close="closeGroup">
        <el-form :model="groupForm" :rules="groupRules" ref="groupFormRef" label-width="80px">
          <el-form-item label="分组名称" prop="name">
            <el-input v-model="groupForm.name" placeholder="请输入分组名称"></el-input>
          </el-form-item>
        </el-form>

        <template #footer>
          <div class="dialog-footer">
            <el-button type="primary" @click="onSubmit">提交</el-button>
            <el-button @click="closeGroup">取消</el-button>
          </div>
        </template>
      </el-dialog>
      <!-- 新增/编辑表单 -->
      <Form ref="formRef" />
      <!-- 人员选择 -->
      <userForm ref="userFormRef" />
      <!-- 移动至分组 -->
      <moveForm ref="moveFormRef" />
      <!-- 视频详情 -->
      <el-dialog v-model="visible" :title="detailData.title" width="830px" :before-close="handleClose">
        <div>
          <div class="dialogHeader">
            <div></div>
            <div class="dialogBtn" @click="refreshUrl">
              <el-icon color="#409efc" :size="20">
                <Refresh />
              </el-icon>
              <div>刷新视频</div>
            </div>
          </div>
          <div v-if="visible || showVideo" class="prism-player" id="player-con"></div>
          <!-- <VideoPlay :videoUrl="detailData.videoUrl" :videoType="detailData.videoType" /> -->
          <!-- <video style="width: 100%; height: 500px" id="video" controls muted="false"></video> -->
          <!-- <iframe src="/static/artcvideo.html" width="100%" height="600px" ref="iframeDom"></iframe> -->
        </div>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="handleClose">关闭</el-button>
          </div>
        </template>
      </el-dialog>
    </div>
  </div>
</template>
<script setup lang="tsx" name="live">
import VideoPlay from "@/components/VideoPlay/videoplay.vue";
import { ElMessage, ElMessageBox, ElTree } from "element-plus";
import { ArrowDown,More } from "@element-plus/icons-vue";
import type Node from "element-plus/es/components/tree/src/model/node";
import { monitorLIVEApi, monitorLiveButtonCode,SysOrg,SysUserPersonnel } from "@/api";
import { sysCamera } from "@/api/interface";
import { useHandleData } from "@/hooks/useHandleData";
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
import { useDictStore } from "@/stores/modules";
import Form from "./components/form.vue";
import userForm from "./components/userForm.vue";
import moveForm from "./components/moveForm.vue";
// import { FormOptEnum, SysDictEnum, MenuTypeDictEnum } from "@/enums";
// import './aliyun-rts-sdk.js'
import "./ali.js";
enum FormOptEnum {
   /** 新增 */
   ADD = "新增",
  /** 编辑 */
  EDIT = "编辑",
  /** 查看 */
  VIEW = "查看",
  /** 删除 */
  DELETE = "删除",
  // 分组推送人
  GroupPushPerson = "分组推送人",
  // 视频推送人
  VideoPushPerson = "视频推送人",
  // 移动
  MOVE = "移动",
  // 分组
  GROUP = "分组"
}
/** 更多下拉菜单命令枚举 */
enum cmdEnum {
  Delete = "删除",
  pushPerson = "推送人"
}
/** 下拉菜单参数接口 */
interface Command {
  row: SysUserPersonnel.SysUserPerInfo;
  command: cmdEnum;
}

/**配置command的参数 */
function command(row: SysUserPersonnel.SysUserPerInfo, command: cmdEnum): Command {
  return {
    row: row,
    command: command
  };
}
function handleCommand(command: Command) {
  switch (command.command) {
    case cmdEnum.Delete:
      ElMessageBox.confirm(`确定要删除此数据吗？`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          onDelete([command.row.id])
        })
        .catch(() => {
    })
      break
    case cmdEnum.pushPerson:
    pushPerson(FormOptEnum.VideoPushPerson, command.row)
      // userManagePersonnelApi.personUnBindDfie({
      //   personId:command.row.personId,
      //   personSetId: command.row.personSets[0].personSetId
      // }).then(res=>{
      //     ElMessage.success('底库解绑成功');
      //     RefreshTable()
      // })
      break;
  }
}
// 分组字段配置
const defaultProps = {
  children: "children",
  label: "name"
};
// 默认高亮
const defaultHighlightKey = ref("");

let treeDada1 = ref([
  {
    id: "",
    name: "全部"
  }
]);
const treeData = ref<any>([]);
var treeRef = ref<InstanceType<typeof ElTree>>();
// 获取摄像头分组
function getGroupList() {
  monitorLIVEApi.groupList({}).then((res:any) => {
    if (res.code == 200) {
      treeData.value = [...treeDada1.value, ...res.data];
    }
  });
}

const groupVisible = ref(false); //是否显示表单
const groupTitle = ref("新增分组");
const groupForm = reactive({
  name: "",
  id: "",
  parentId: ""
});
const groupFormRules = ref({
});
const groupRules = ref({
  name: [{ required: true, message: "请输入分组名称", trigger: "blur" }]
});
const groupFormRef = ref<any>(null);
const closeGroup = () => {
  groupVisible.value = false;
  groupFormRef.value.resetFields();
  groupForm.name = "";
  groupForm.id = "";
  groupForm.parentId = "";
};
const groupFormType = ref<any>(null);
// 新增编辑分组
const append = (type: string, data: Tree) => {
  groupVisible.value = true;
  groupFormType.value = type
  if (type == "edit") {
    groupTitle.value = "编辑分组";
    groupForm.name = data.name;
    groupForm.id = data.id;
  } else if(type == "addChild") {
    groupTitle.value = "新增分组";
    groupForm.parentId = data.id
  } else {
    groupTitle.value = "新增分组";
  }
};
// 删除分组
async function remove(id: string[], msg: string) {
  await useHandleData(monitorLIVEApi.deleteGroup, { id }, msg);
  getGroupList();
}
// 提交分组
const onSubmit = () => {
  groupFormRef.value.validate((valid: any) => {
    if (valid) {
      let params: any = reactive({
        id: "",
        name: groupForm.name,
        parentId: groupForm.parentId
      });
      console.log(groupFormType)
      if (groupFormType.value == 'add') {
        delete params.parentId;
        monitorLIVEApi.addGroup(params).then((res:any) => {
          if (res.code == 200) {
            getGroupList();
            closeGroup();
          }
        });
      } else if(groupFormType.value == 'edit') {
        params.id = groupForm.id;
        delete params.parentId;
        monitorLIVEApi.updateGroup(params).then((res:any) => {
          if (res.code == 200) {
            getGroupList();
            closeGroup();
          }
        });
      } else if(groupFormType.value == 'addChild') {
        delete params.id;
        monitorLIVEApi.addGroup(params).then((res:any) => {
          if (res.code == 200) {
            getGroupList();
            closeGroup();
          }
        });
      }
      closeGroup();
    } else {
      return false;
    }
  });
};
// 摄像头分组过滤
interface Tree {
  [key: string]: any;
  id: any;
  label: string;
  children?: Tree[];
}
const filterText = ref("");

watch(filterText, val => {
  treeRef.value!.filter(val);
});

const filterNode = (value: string, data: Tree) => {
  if (!value) return true;
  return data.name.includes(value);
};

const handleNodeClick = (data: Tree) => {
  proTable.value!.pageable.pageNum = 1;
  proTable.value!.searchParam.groupId = data.id;
  proTable.value!.search();
};
const visible = ref(false); //是否显示表单

// 获取 ProTable 元素，调用其获取刷新数据方法（还能获取到当前查询参数，方便导出携带参数）
const proTable = ref<ProTableInstance>();
const dictStore = useDictStore();

// 表格配置项
const columns: ColumnProps<sysCamera.MonitorInfo>[] = [
  { type: "selection", fixed: "left", width: 80 },
  {
    prop: "sensorId",
    label: "摄像头ID"
  },
  {
    prop: "sensorName",
    label: "摄像头名称"
  },
  {
    prop: "fieldName",
    label: "所属学校"
  },
  {
    prop: "directUrlIp",
    label: "设备ip"
  },
  {
    prop: "resWidth",
    label: "分辨率",
    render: row => {
      return row.row.resWidth + "*" + row.row.resHeight;
    }
  },
  { prop: "operation", label: "操作", width: 250, fixed: "right" }
];
// 移动分组禁用
const moveFormRef = ref<InstanceType<typeof Form> | null>(null);
function omMove(opt: FormOptEnum, record: {} | SysOrg.SysOrgInfo = {}) {
  console.log(record,"record")

  moveFormRef.value?.omMove({ opt: opt, records: record, successful: RefreshTable });
}
/**
 * 删除
 * @param ids  id数组
 */
async function onDelete(ids: string[], msg: string) {
  console.log(1)
  return;
  // 二次确认 => 请求api => 刷新表格
  await useHandleData(monitorLIVEApi.delete, { ids }, msg);
  RefreshTable();
}

/**
 * 刷新表格
 */
function RefreshTable() {
  proTable.value?.refresh();
}
function RefreshTables() {
  proTable.value?.refresh();
  getGroupList();
}
// 表单引用
const formRef = ref<InstanceType<typeof Form> | null>(null);
/**
 * 打开表单
 * @param opt  操作类型
 * @param record  记录
 */
function onOpen(opt: FormOptEnum, record: {} | SysOrg.SysOrgInfo = {}) {
  formRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable });
}

// 人员选择
// 表单引用
const userFormRef = ref<InstanceType<typeof Form> | null>(null);
/**
 * 打开表单
 * @param opt  操作类型
 * @param record  记录
 */
function pushPerson(opt: FormOptEnum, record: {} | SysOrg.SysOrgInfo = {}) {
  userFormRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTables });
}
// 详情数据
// let detailData: globalThis.Ref<{}>
let detailData = reactive({
  title: "",
  videoUrl: "",
  sensorId: "",
  streamId: "",
  videoToken: "",
  videoType: ""
});
function onDetail(row: any) {
  visible.value = true;
  detailData.sensorId = row.sensorId;
  detailData.title = row.sensorName + "(" + row.sensorId + ")";
  getUrl();
}
// 刷新
const showVideo = ref(false);
function refreshUrl() {
  stopUrl();
  showVideo.value = false;
  setTimeout(() => {
    showVideo.value = true;
    getUrl();
  }, 1000);
}
let num = 1;
function getUrl() {
  detailData.videoType = "m3u8";
  setTimeout(async () => {
    await monitorLIVEApi.detail({ sensorId: detailData.sensorId }).then((res:any) => {
      let { code, data } = res;

      if (code == '200') {
        // window.location.origin+
        detailData.videoUrl = "";
        detailData.videoUrl = data.rtsPullStreamUrls[0].url;
        // detailData.videoUrl = data.pullStreamUrls[2].url;
        detailData.streamId = data.streamId;
        detailData.videoToken = data.videoToken;
        // getvideo1()
        getvideo2();
      }
    });
  });
}
function getvideo1() {
  let aliRts = new AliRTS();
  let pullStreamUrl = detailData.videoUrl;
  const mediaEle = document.querySelector("video");
  aliRts.on("onError", err => {
    console.log(`errorCode: ${err.errorCode}`);
    console.log(`message: ${err.message}`);
  });

  const PLAY_EVENT = {
    CANPLAY: "canplay",
    WAITING: "waiting",
    PLAYING: "playing"
  };

  aliRts.on("onPlayEvent", play => {
    console.log(">>play.event:" + play.event);
    if (play.event === PLAY_EVENT.CANPLAY) {
      // 拉流可以播放
      console.log("可以播放");
    } else if (play.event === PLAY_EVENT.WAITING) {
      // 拉流卡顿等待缓冲中 （仅Chrome）
      console.log("拉流卡顿等待缓冲中");
    } else if (play.event === PLAY_EVENT.PLAYING) {
      // 拉流卡顿结束恢复播放 （仅Chrome）
      console.log("拉流卡顿结束恢复播放");
    }
  });
  aliRts.startLiveStream(pullStreamUrl, mediaEle);
  // aliRts.startLiveStream(pullStreamUrl, mediaEle);
}
let player = ref<any>(null);
function getvideo2() {
  var options = {
    id: "player-con",
    source: detailData.videoUrl + "&subaudio=no&jitterbuffer=6000",
    // "rtsFallbackSource": "降级地址，如HLS",
    width: "100%",
    height: "500px",
    autoplay: true,
    isLive: true,
    playsinline: true,
    skipRtsSupportCheck: false, // 对于不在 https://help.aliyun.com/document_detail/397569.html 中的浏览器，可以传 true 跳过检查，强制使用 RTS（有风险，需要自测保证）

    /**
     * RTS 拉流超时会默认重试
     * 以下两个参数用来控制降级之前的重试策略，比如 3000 毫秒超时，重试一次，如果再拉不到流就降级，那么总共等待 6000 毫秒降级
     **/
    // RTS 多久拉不到流会重试，默认 3000 ms
    rtsLoadDataTimeout: 1500,

    // RTS 拉不到流重试的次数，默认 5，此参数建议设为 1，即重试 1 次后降级，可以减少降级等待时间
    liveRetry: 1
  };

  player.value = new Aliplayer(options, function () {
    /* player ready */
  });

  // 降级时会触发此事件
  player.value.on("rtsFallback", function (event:any) {
    console.log("[EVENT]rtsFallback", event.paramData);
    // event.paramData.reason 降级的原因
    // event.paramData.fallbackUrl 降级到的地址
  });

  player.value.on("error", function (event:any) {
    console.log("[EVENT]error", event.paramData);
  });
  player.value.setVolume(0)
  // 当RTS拉流成功时触发，通过订阅该事件，可以获取到RTS TraceId
  player.value.on("rtsTraceId", function (data:any) {
    console.log("[EVENT]rtsTraceId", data.paramData);
    // event.paramData.traceId 拉流的TraceId
    // event.paramData.source 当前RTS流的播放地址
  });
}
const handleClose = () => {
  visible.value = false;
  detailData.videoUrl = "";
  detailData.videoType = "";
  stopUrl();
  if (player.value) {
    player.value.dispose();
  }
};
function stopUrl() {
  detailData.videoUrl = "";
  if (player.value) {
    player.value.dispose();
  }
  let params = {
    sensorId: detailData.sensorId,
    streamId: detailData.streamId,
    videoToken: detailData.videoToken
  };
  setTimeout(async () => {
    await monitorLIVEApi.stopUrl(params).then((res:any) => {
      let { code, data, msg } = res;

      if (code == 200) {
        // ElMessage.success(msg);
      }
    });
  });
}

onMounted(() => {
  getGroupList();
});
</script>

<style lang="scss" scoped>
@import "https://g.alicdn.com/apsara-media-box/imp-web-player/2.16.3/skins/default/aliplayer-min.css";
@import "./index.scss";
.dialogHeader {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 20px;
  font-size: 18px;
  color: #409efc;
  cursor: pointer;
  .dialogBtn {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
}
</style>
