import orders from "./orders";
import dayjs from 'dayjs';

export default {
  namespaced: true,
  state: {
    ws: null,
    include: [], //需要包含的deviceHeadId，包含后dataSet中将进行保存
    url: "", //mqtt地址
    dataSet: {
      //数据集
      /* deviceHardId: {
        type(如258): {}
      } */
    },
    orders, //所有指令
    callbackList: [], //ws消息callback队列
    userInfo: {}, //用户信息
  },
  mutations: {
    /**
     * 单纯的给state赋值
     * @param {*} param0
     * @param {*} data {key: '', value}
     */
    setState(state, data) {
      try {
        state[data.key] = data.value;
      } catch (e) {
        console.log("setDate err", e);
      }
    },
    setWs(state, data) {
      state.ws = data;
    },
    setInclude(state, data) {
      state.include = data;
    },
    setUrl(state, data) {
      state.url = data;
    },
    setDataSet(state, data) {
      let temp = {};
      Object.keys(data).forEach((key) => {
        temp[key] = data[key];
      });
      state.dataSet = temp;
    },
    setCallbackList(state, data) {
      state.callbackList = data;
    },
    setUserInfo(state, data) {
      state.userInfo = data;
    },
  },
  actions: {
    /**
     *
     * @param {*} param0
     * @param {*} param1
     * @param {string} param1.url   //地面站ws的url
     * @param {object} param1.userInfo  //用户信息对象
     * @param {string} param1.userInfo.username   //用户名
     * @param {string} param1.userInfo.token  //用户token
     * @param {string} param1.userInfo.appId  //用户的appId
     * @param {Function} param1.loginCallback //登录成功回调
     * @returns ws连接成功返回
     */
    init({ commit, state }, { url, userInfo, loginCallback }) {
      const ws = new WebSocket(url);
      commit("setWs", ws);
      commit("setUserInfo", userInfo);

      ws.onclose = (data) => {
        console.log("onclose", data);
      };

      return new Promise((resolve, reject) => {
        ws.onopen = () => {
          const wsData = {
            type: 100,
            systemCode: "mmc",
            state: 1,
            ...userInfo,
          };
          ws.send(JSON.stringify(wsData));
          resolve();
        };
        ws.onerror = (error) => {
          console.log("error", error);
          reject(error);
        };
        ws.onmessage = (e) => {
          let metadata = {};
          try {
            metadata = JSON.parse(e.data);
          } catch (err) {
            // console.log('ws:', e.data)     //跳过心跳包
            return;
          }
          //登录成功事件
          if (metadata.msgnum == 4118) {
            loginCallback && loginCallback();
          }

          if (metadata.deviceData) {
            try {
              if (typeof metadata.deviceData == "string") {
                metadata.deviceData = JSON.parse(metadata.deviceData);
              }

              const deviceHardId = metadata.deviceData.deviceHardId;

              if (state.include.includes(deviceHardId)) {
                if (!state.dataSet[deviceHardId]) {
                  state.dataSet[deviceHardId] = {};
                }
                metadata.$time = Date.now(); // 打上时间戳
                metadata.$timeStr = dayjs(data.$time).format('YYYY-MM-DD hh:mm:ss');
                state.dataSet[deviceHardId] = metadata;
                commit("setDataSet", state.dataSet);
              }
            } catch (e) {
              console.log(e);
            }
          }

          state.callbackList.forEach((cb) => {
            cb(metadata);
          });
        };
      });
    },
    /**
     * 断开ws连接
     * @param {} param0
     */
    end({ state, commit }) {
      state.ws && state.ws.close();
      commit("setWs", null);
      commit("setUserInfo", {});
    },
    /**
     * 订阅
     * @param {*} deviceHardId
     */
    subscribe({ state, commit, dispatch }, deviceHardId) {
      if (!deviceHardId) {
        return deviceHardId;
      }
      let list = [...state.include];
      let find = list.find((id) => {
        return deviceHardId === id;
      });
      if (!find) {
        list.push(deviceHardId);
      }
      commit("setInclude", list);
      dispatch("order", { order: "订阅", data: {}, deviceHardId });
    },
    /**
     * 取消订阅
     * @param {*} deviceHardId
     * @returns
     */
    unsubscribe({ state, commit, dispatch }, deviceHardId) {
      if (!deviceHardId) {
        return deviceHardId;
      }

      let list = [...state.include];
      list = list.filter((id) => {
        return deviceHardId !== id;
      });
      if (state.dataSet[deviceHardId]) {
        state.dataSet[deviceHardId] = undefined;
        commit("setDataSet", state.dataSet);
      }
      commit("setInclude", list);
      dispatch("order", { order: "取消订阅", data: {}, deviceHardId });
    },
    /**
     * 发布消息到地面站
     * @param {*} publication
     * @param {*} callback
     * @param {*} options
     * @param {*} type
     */
    publish({ state }, { type, cmdFunction, data, deviceHardId }) {
      state.ws.send(
        JSON.stringify({
          type,
          systemCode: "mmc",
          state: 1, //0 地面站（无人机），1 客户端或者web ，2 HTTP接口
          username: state.userInfo.username,
          data: {
            cmdFunction,
            ...data,
          },
          deviceHardId,
        })
      );
    },
    /**
     * 全部指令
     */
    order({ state, dispatch }, { order, data, deviceHardId }) {
      if (state.orders[order] === undefined) {
        throw "该命令不存在！";
      }

      let orderArr = state.orders[order].split(",");

      dispatch("publish", {
        type: Number(orderArr[0]),
        cmdFunction: Number(orderArr[1]),
        data,
        deviceHardId,
      });
    },
    /**
     * 添加回调
     * @param {*} param0
     * @param {*} cb
     */
    addCallback({ state, commit }, cb) {
      let list = [...state.callbackList];
      list.filter((cb1) => {
        return cb !== cb1;
      });
      list.push(cb);
      commit("setCallbackList", list);
    },
    /**
     * 移除回调
     * @param {*} param0
     * @param {*} cb
     */
    removeCallback({ state, commit }, cb) {
      let list = [...state.callbackList];
      list = list.filter((cb1) => {
        return cb !== cb1;
      });
      commit("setCallbackList", list);
    },
  },
};
