// 工具函数
import {
  CONFIG,
  WarningConfig
} from '@/common/const.js';
import store from '../store/index.js';
import {
  Message
} from 'element-ui'

/**
 * @auto 刘彬瑜
 * @todo 封装日期格式化，这里代替moment，因为moment太大了
 * @param {Date} date date对象
 * @param {String} fmt 输出的格式(参考moment)
 * @return 
 */
export function dateFormat(date, fmt) {
  var o = {
    "M+": date.getMonth() + 1, //月份 
    "D+": date.getDate(), //日 
    "H+": date.getHours(), //小时 
    "m+": date.getMinutes(), //分 
    "s+": date.getSeconds(), //秒 
    "z": ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][date.getDay()], // 中文星期
    "e": ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][date.getDay()], // 英文星期
    "q+": Math.floor((date.getMonth() + 3) / 3), //季度 
    "x": date.getMilliseconds() //毫秒 
  };
  if (/(Y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    }
  }
  return fmt;
}

/**
 * @todo: 防抖函数
 * @param: {Function} func 目标方法
 * @param: {Number} wait 延时时间
 * @param: {Boolean} immediate 是否立即执行
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result
  const later = function() {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp
    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }
  return function(...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }
    return result
  }
}

/**
 * @todo 根据信号状态或名字，返回对应的报警对象
 * @param {Number} state 信号状态
 * @param {String} name 报警名称
 * @return {Object} warn 报警对象
 */
export function getWarnItem(state, name) {
  if (state) {
    for (let key in WarningConfig) {
      if (WarningConfig[key].state == parseInt(state)) {
        return WarningConfig[key];
      }
    }
  }
  if (name) {
    for (let key in WarningConfig) {
      if (WarningConfig[key].name == name) {
        return WarningConfig[key];
      }
    }
  }
  return null;
}

/**
 * @todo 根据信号状态，返回对应的报警颜色
 * @param {Number} state 信号状态
 * @param {Boolean} gradients 是否渐变，1是0否
 * @return {String} color 颜色，如果选择了渐变，则返回数组[color, color2]
 */
export function getWarnColor(state, gradients) {
  for (let key in WarningConfig) {
    if (WarningConfig[key].state == parseInt(state)) {
      return gradients ? [WarningConfig[key].color, WarningConfig[key].color2] : WarningConfig[key].color;
    }
  }
  return gradients ? ['#fff', '#fff'] : '#fff'; //如果找不到，返回白色，正常应该是能找到的
}
/**
 * @todo 根据报警名称，返回对应的报警颜色
 * @param {String} name 报警等级名称
 * @param {Boolean} gradients 是否渐变，1是0否
 * @return {String} color 颜色，如果选择了渐变，则返回数组[color, color2]
 */
export function getWarnColorByName(name, gradients) {
  for (let key in WarningConfig) {
    if (WarningConfig[key].name == name) {
      return gradients ? [WarningConfig[key].color, WarningConfig[key].color2] : WarningConfig[key].color;
    }
  }
  return gradients ? ['#fff', '#fff'] : '#fff'; //如果找不到，返回白色，正常应该是能找到的
}

/**
 * @todo: 根据给定值的数组和阈值，返回对应的报警比例
 * @param {Array} arr 一组值
 * @param {Object} threshold 阈值，如果不传入阈值，则按数据里的信号状态统计，传了按阈值重新统计
 * @return {Object} distribution 分布，例如{'02': 600, '03': 200}，代表信号状态为2的报警有600次，信号状态为3的报警有200次
 */
export function getWarnDistribution(arr, threshold) {
  if (!arr || !arr.length) return {};
  let count = {};
  // 按信号状态统计
  if (!threshold) {
    for (let i = (arr.length - 1); i >= 0; i--) {
      const state = arr[i]?.toString().substr(-2) || 0; // 取出信号状态
      if (count[state]) {
        count[state]++;
      } else {
        count[state] = 1;
      }
    }
    // 按阈值统计
  } else {
    // 整理各个等级的阈值
    let warnLevel = [];
    for (let key in WarningConfig) {
      if (WarningConfig[key].warnLevel && (key + 'RuleExclude' in threshold)) {
        warnLevel.push({
          state: WarningConfig[key].state,
          max: threshold[key + 'RuleMaxValue'],
          min: threshold[key + 'RuleMinValue'],
          exclude: threshold[key + 'RuleExclude'],
          level: WarningConfig[key].warnLevel
        })
      }
    }
    warnLevel.sort((a, b) => b.level - a.level); // 按报警等级,从低到高排序
    for (let i = (arr.length - 1); i >= 0; i--) {
      let state = 0;
      let val = parseFloat(arr[i]);
      // 遍历每个报警等级,判断是否报警，这里是先判断低的，比如先判断趋势报警是否触发，如果没触发，则state没有赋值，则跳过（未报警），如果触发了，再找上一个报警等级（预警），如果触发了，更新state
      for (let level of warnLevel) {
        if ((level.exclude && ((level.min !== '' && val <= level.min) || (level.max !== '' && val >= level.max))) || (!
            level.exclude && ((level.min !== '' && level.max !== '' && val >= level.min && val <= level.max) || (
              level.min !== '' && level.max === '' && val >= level.min) || (
              level.min === '' && level.max !== '' && val <= level.max)))) {
          state = level.state;
        }
      }
      if (!state) continue;
      if (count[state]) {
        count[state]++;
      } else {
        count[state] = 1;
      }
    }
  }
  return count;
}

// 正态分布数据
export function initDataNormal() {
  // let data = {
  // 	xAxis: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
  // 	dataList: [{name: 'a', value: [0, 0.02, 0.12, 0.42, 0.64, 0.7, 0.64, 0.42, 0.12, 0.02, 0]}],
  // }
  let data = [
    [0, 0],
    [1, 0.1],
    [2, 0.2],
    [3, 0.4],
    [4, 0.7],
    [5, 1.2],
    [6, 1.95],
    [7, 2.7],
    [8, 3.4],
    [9, 4.05],
    [10, 4.6],
    [11, 5.15],
    [12, 5.6],
    [13, 5.95],
    [14, 6.2],
    [15, 6.35],
    [16, 6.44],
    [17, 6.48],
    [18, 6.44],
    [19, 6.35],
    [20, 6.2],
    [21, 5.95],
    [22, 5.6],
    [23, 5.15],
    [24, 4.6],
    [25, 4.05],
    [26, 3.4],
    [27, 2.7],
    [28, 1.95],
    [29, 1.2],
    [30, 0.7],
    [31, 0.4],
    [32, 0.2],
    [33, 0.1],
    [34, 0]
  ]
  return data;
}

/**
 * @todo 导出数据到文件
 * @param {Json} data json格式的数据
 * @param {String} name 文件名
 * @param {String} type 文件后缀
 * @return 无
 */
export function exportDataToFile(data, name, type) {
  var urlObject = window.URL || window.webkitURL || window;
  var export_blob = type == '.csv' ? new Blob(['\uFEFF' + data], { type: 'text/csv;charset=utf-8;' }) : new Blob([data]);
  var save_link = document.createElement('a');
  save_link.href = urlObject.createObjectURL(export_blob);
  save_link.download = name;
  save_link.click();
}

/**
 * @todo 将字符串按一定长度换行，目前用于处理图表数据名称过长
 * @param {String} str 待处理的字符串
 * @param {Number} len 切割的每一块的长度
 * @return 处理后的字符串
 */
export function sliceString(str, len) {
  let newStr = '';
  for (let i = 0; i < str.length / len; i++) {
    newStr += str.slice(i * len, i * len + len);
    newStr += (i < str.length / len - 1) ? '\n' : '';
  }
  return newStr;
}

/**
 * @todo 数字显示n位小数，如果没这么多小数，则不处理
 * @param {Number} value 待处理的数值
 * @param {Number} n 四舍五入保留位数
 * @return 处理后的数字
 */
export function toFixedNum(value, n) {
  if (!value) return value;
  value = parseFloat(value);
  let arr = value.toString().split('.');
  if (arr.length == 1 || arr[1].length <= n) return value;
  return value.toFixed(n);
}

/**
 * @todo 将实时数据转化为历史数据，即将每一次的实时数据记录下来，保留n位，用于折线图展示，注意每次只能新增一个点值
 * @param {Object} oldData 旧数据
 * @param {Object} newData 新实时数据
 * @param {Number} n 保留的位数
 * @return 无返回，会直接在旧数据上新增新数据
 */
export function chartDataRecord(oldData, newData, n) {
  if (oldData.xAxis[oldData.xAxis.length - 1] == newData.xAxis[0]) return; // 如果时间戳相同，则判断为重复数据，不添加
  // 最多保留n位，将x轴和每个数据的y轴删掉，只剩n-1位
  if (oldData.xAxis.length >= n) {
    oldData.xAxis = oldData.xAxis.slice(-1 * (n - 1));
    oldData.dataList.forEach(i => {
      i.value = i.value.slice(-1 * (n - 1));
      if (i.value2) i.value2 = i.value2.slice(-1 * (n - 1));
    });
  }
  oldData.xAxis.push(newData.xAxis[0]); // 添加x轴
  // 遍历datalist，找到相同的数据对象的值添加进去，没找到则添加0
  oldData.dataList.forEach(i => {
    i.value.push(newData.dataList.find(j => j.kksCode == i.kksCode)?.value[0] || 0);
    if (i.value2) i.value2.push(newData.dataList.find(j => j.kksCode == i.kksCode)?.value2[0] || 0);
  });
}

/**
 * @todo 将数据转化为图表数据，将相同监测点，不同机组的数据归类，用于柱状图展示
 * @param {Object} data 接口数据，格式为{xAxis: [1548937293(时间戳)], dataList: [{name: '1F某某监测点', kksCode: 'C0A00101MKD11CT601A', value: [11]}, {name: '2F某某监测点', value: [22]}, {name: '1F某某监测点2', value: [33]}, {name: '2F某某监测点2', value: [44]}]}
 * @return 处理后的新数据，格式为{xAxis: ['某某监测点', '某某监测点2'], dataList: [{name: 'C0A00101', value: [11, 33]}, {name: 'C0A00102', value: [22, 44]}]}
 */
export function chartDataTransform(data) {
  let newData = {
    xAxis: [],
    dataList: []
  }
  // 测点按机组排序
  data.dataList.sort((a, b) => parseInt(characterDelCrewCode(a.kksCode)[0].substr(6)) - parseInt(characterDelCrewCode(
    a.kksCode)[0].substr(6)));
  // 遍历监测点
  for (let i = 0; i < data.dataList.length; i++) {
    let item = data.dataList[i]; // 单个监测点
    let arr = characterDelCrewCode(item.kksCode); // 前半截为机组code
    let nameArr = characterDelCrewNo(item.name); // 分离名字
    if (!newData.dataList.find(i => i.name == arr[0])) newData.dataList.push({
      name: arr[0],
      value: []
    }); // 判断是否是新的机组，是则重新建一个对应的对象
    // 添加监测点值
    let index = newData.xAxis.findIndex(i => i == nameArr[1]); // 数据x轴的索引，用于添加到对应的y轴里
    // 如果是新的监测点,则新增
    if (index == -1) {
      newData.xAxis.push(nameArr[1]);
      index = newData.xAxis.length - 1; // 更新索引为最后添加的这个
    }
    newData.dataList.find(i => i.name == arr[0]).value[index] = item.value[0]; // 这里重新找了一次，正常应该是一定可以找到的，因为如果没有，在前面已经添加了
  }
  // 转换机组标题
  newData.dataList.forEach(i => i.name = getDeviceNameById(i.name, 1));
  // 测点名后加单位
  newData.xAxis = newData.xAxis.map(i => {
    return i + '（' + (data.dataList.find(j => j.name.indexOf(i) != -1).cpunit || '') + '）';
  })
  return Object.assign(data, newData);
}

/**
 * @todo 将数据转化为图表数据，将相同监测点，不同测点的数据归类，用于柱状图展示，区别于上一个，x轴不一样了
 * @param {Object} data 接口数据，格式为{xAxis: [1548937293(时间戳)], dataList: [{name: '1F某某监测点', kksCode: 'C0A00101MKD11CT601A', value: [11]}, {name: '2F某某监测点', value: [22]}, {name: '1F某某监测点2', value: [33]}, {name: '2F某某监测点2', value: [44]}]}
 * @return 处理后的新数据，格式为{xAxis: ['C0A00101', 'C0A00102'], dataList: [{name: '某某监测点', value: [11, 22]}, {name: '某某监测点2', value: [33, 44]}]}
 */
export function chartDataTransform2(data) {
  let newData = {
    xAxis: [],
    dataList: []
  }
  // 测点按机组排序
  data.dataList.sort((a, b) => parseInt(characterDelCrewCode(a.kksCode)[0].substr(6)) - parseInt(characterDelCrewCode(
    a.kksCode)[0].substr(6)));
  // 遍历监测点
  for (let i = 0; i < data.dataList.length; i++) {
    let item = data.dataList[i]; // 单个监测点
    let arr = characterDelCrewCode(item.kksCode); // 前半截为机组code
    let nameArr = characterDelCrewNo(item.name); // 分离名字
    if (!newData.dataList.find(i => i.name == nameArr[1])) newData.dataList.push({
      name: nameArr[1],
      value: []
    }); // 判断是否是新的测点，是则重新建一个对应的对象
    // 添加监测点值
    let index = newData.xAxis.findIndex(i => i == arr[0]); // 数据x轴的索引，用于添加到对应的y轴里
    // 如果是新的监测点,则新增
    if (index == -1) {
      newData.xAxis.push(arr[0]);
      index = newData.xAxis.length - 1; // 更新索引为最后添加的这个
    }
    newData.dataList.find(i => i.name == nameArr[1]).value[index] = item.value[0]; // 这里重新找了一次，正常应该是一定可以找到的，因为如果没有，在前面已经添加了
  }
  // 转换机组标题
  newData.xAxis = newData.xAxis.map(i => getDeviceNameById(i, 1));
  // 测点名后加单位
  newData.dataList.forEach(i => {
    i.name += '（' + (data.dataList.find(j => j.name.indexOf(i.name) != -1).cpunit || '') + '）';
  })
  return Object.assign(data, newData);
}

/**
 * @todo 将数据转化为图表数据，将相同监测点，不同机组的数据归类，用于柱状图展示
 * @param {Object} data 接口数据，格式为{xAxis: [1548937293(时间戳)], dataList: [{name: '1F某某监测点', kksCode: 'C0A00101MKD11CT601A', value: [11]}, {name: '2F某某监测点', value: [22]}, {name: '1F某某监测点2', value: [33]}, {name: '2F某某监测点2', value: [44]}]}
 * @return 处理后的新数据，格式为{xAxis: ['1F某某监测点', '2F某某监测点', '1F某某监测点2', '2F某某监测点2'], dataList: [{value: [11, 22, 33, 44]}]}
 */
export function chartDataTransform3(data) {
  let newData = {
    xAxis: [],
    dataList: [{
      value: []
    }]
  }
  // 遍历监测点
  for (let i = 0; i < data.dataList.length; i++) {
    let item = data.dataList[i]; // 单个监测点
    if (!item.name) continue
    newData.xAxis.push(item.name + '（' + (item.cpunit || '') + '）'); // 名字后面加上单位
    newData.dataList[0].value.push(item.value[0]);
  }
  return Object.assign(data, newData);
}

/**
 * @todo 返回范围内的随机数据，默认整数
 * @param {Number} min 最小值
 * @param {Number} max 最大值
 * @param {Number} n 保留的位数
 * @return 随机数据
 */
export function randomData(min, max, n = 0) {
  return (Math.random() * (parseFloat(max) - parseFloat(min)) + parseFloat(min)).toFixed(n);
}

/**
 * @todo 从测点kkscode中分离出机组code（也就是最开始的8位）
 * @param {String} kksCode 测点码
 * @return {Array} [0] - 机组code， [1] - 去掉机组编号后的测点code
 */
export function characterDelCrewCode(kksCode) {
  const len = 8;
  return [kksCode.substr(0, len), kksCode.substr(len)];
}

/**
 * @todo 从测点名字中分离出机组序号（也就是最开始的数字），以及序号后的名字
 * @param {String} name 测点名
 * @return {Array} [0] - 机组序号， [1] - 去掉机组编号后的测点名
 */
export function characterDelCrewNo(name) {
  let reg = new RegExp('^\\d+' + CONFIG.CHARACTER_TAB, 'i'); // 匹配数字+标识开头
  let no = '';
  let res = name.replace(reg, (a, b, c, d, e, f) => {
    no = a.substr(0, a.length - CONFIG.CHARACTER_TAB.length);
    return '';
  });
  return [no, res];
}

/**
 * @todo 下载文件
 * @param {Blob} blob 文件流
 * @return {String} fileName 文件名
 */
export function downloadFile(blob, fileName) {
  // IE10+下载
  if (window.navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, fileName);
  } else {
    const link = document.createElement('a');
    link.download = fileName;
    link.style.display = 'none';
    link.href = window.URL.createObjectURL(blob);
    document.body.appendChild(link);
    link.click();
    window.URL.revokeObjectURL(link.href);
    document.body.removeChild(link);
  }
}

/**
 * @todo 执行用户注销，用于token过期时的用户强制退出
 * @param 无
 * @return 无
 */
export function userLogout() {
  Message({
    message: '用户过期，请重新登录',
    type: 'error'
  });
  localStorage.removeItem('electric_user');
  localStorage.removeItem('electric_user_token');
  localStorage.removeItem('electric_factory');
  localStorage.removeItem('electric_factoryList');
  location.reload()
}

/**
 * @auto 刘彬瑜
 * @todo 封装浮点数计算
 * @param arg1，arg2待计算参数
 * @return 计算后的结果
 */
export const M = {
  // 除法函数
  Div: function(arg1, arg2) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var t1 = 0,
      t2 = 0,
      r1, r2;
    try {
      t1 = arg1.toString().split(".")[1].length;
    } catch (e) {}
    try {
      t2 = arg2.toString().split(".")[1].length;
    } catch (e) {}
    r1 = Number(arg1.toString().replace(".", ""));
    r2 = Number(arg2.toString().replace(".", ""));
    return (r1 / r2) * Math.pow(10, t2 - t1);
  },
  // 加法函数
  Add: function(arg1, arg2) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var r1 = 0,
      r2 = 0,
      m;
    try {
      r1 = arg1.toString().split(".")[1].length
    } catch (e) {}
    try {
      r2 = arg2.toString().split(".")[1].length
    } catch (e) {}
    m = Math.pow(10, Math.max(r1, r2));
    return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
  },
  // 减法函数
  Sub: function(arg1, arg2) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var r1 = 0,
      r2 = 0,
      m, n;
    try {
      r1 = arg1.toString().split(".")[1].length
    } catch (e) {}
    try {
      r2 = arg2.toString().split(".")[1].length
    } catch (e) {}
    m = Math.pow(10, Math.max(r1, r2));
    //动态控制精度长度
    n = (r1 >= r2) ? r1 : r2;
    return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
  },
  // 乘法函数
  Mul: function(arg1, arg2) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var m = 0,
      s1 = arg1.toString(),
      s2 = arg2.toString();
    try {
      m += s1.split(".")[1].length
    } catch (e) {}
    try {
      m += s2.split(".")[1].length
    } catch (e) {}
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  },
}

/**
 * @auto 刘彬瑜
 * @todo 动态加载js文件
 * @param {String} src js文件地址
 * @return {Promise} 加载结果
 */
export function loadJs(src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement('script')
    script.type = "text/javascript"
    script.src = src
    script.onload = () => resolve()
    script.onerror = () => reject()
    document.getElementsByTagName('body')[0].appendChild(script)
  })
}

/**
 * @auto 刘彬瑜
 * @todo 根据数据计算特征分布，统计数据在每个数据段出现的次数
 * @param {Array} value 数据数组
 * @return {Array} xAxis 数据段
 * @return {Array} yAxis 当前数据段的数据数量
 * @return {Array} arr x和y结合的二维数组，例如[[1, 2], [2.1,5], [3.02, 1]]表示：数据中1（包含）~2.1（不包含）有2个，2.1~3.02有5个，3.02有一个
 */
export function gaosi(value) {
  const size = 50; // 分成20份
  let max = value[0],
    min = value[0];
  // 记录最大值最小值
  for (let i = (value.length - 1); i >= 0; i--) {
    if (parseFloat(value[i]) < min) min = value[i];
    if (parseFloat(value[i]) > max) max = value[i];
  }
  const step = M.Div(Math.ceil((M.Sub(max, min) / size) * 100), 100); // x轴的间段长度，这里做了向上取整，以保证一定能落到x轴里，同时保留两位
  const xAxis = [];
  // 处理x轴（最小值为起点，最大值为终点，step为间距
  for (let i = 0; i <= size; i++) {
    xAxis.push(M.Add(min, M.Mul(step, i)));
  }
  const yAxis = new Array(xAxis.length).fill(0);
  // 遍历值，公式：取整（（当前值 - 最小值） / 间距）
  for (let i = (value.length - 1); i >= 0; i--) {
    yAxis[parseInt(M.Div(M.Sub(value[i], min), step))]++;
  }
  // 合并二维
  const arr = xAxis.map((x, i) => [x, yAxis[i]]);
  return {
    xAxis,
    yAxis,
    arr
  }
}

/**
 * @auto 刘彬瑜
 * @todo 根据机组id获取机组名
 * @param {String} id 机组id(code)
 * @param {Boolean} short 是否使用简称,默认不使用
 * @return {String} name 机组名
 */
export function getDeviceNameById(id, short = false) {
  let name = '';
  if (store.state.$x_factory) {
    name = store.state.$x_factory.plantDevices.find(i => i.deviceId == id)?.deviceName || '';
  } else if (store.state.$x_factoryList) {
    store.state.$x_factoryList.forEach(f => {
      f.plantDevices.forEach(i => {
        if(i.deviceId == id) name = (short && i.shortName) ? i.shortName : i.deviceName;
        return;
      })
      if(name) return;
    })
  }
  // if (name && short) {
  //   return changeDeviceNameToShort(name);
  // }
  return name;
}

/**
 * @auto 刘彬瑜
 * @todo 根据机组名获取机组id
 * @param {String} name 机组名
 * @return {String} id 机组id(code)
 */
export function getDeviceIdByName(name) {
  // let id = '';
  // if (store.state.current.deviceList) {
  //   id = store.state.current.deviceList.find(i => i.deviceName == name)?.deviceId || '';
  // }
  // return id;
}

/**
 * @auto 刘彬瑜
 * @todo 将机组名转为简写
 * @param {String} name 机组名
 * @return {String} 机组名，简写
 */
export function changeDeviceNameToShort(name) {
  return (name.match('^\\d+')?.[0] || '') + '#';
}

/**
 * @auto 刘彬瑜
 * @todo 将字符串用逗号分隔，做成map映射，便于查询是否存在
 * @param {String} str 需要处理的字符串
 * @param {Boolean} lowerCase 是否区分大小写比较
 * @return {Function} 返回一个函数，用于查询，比如const checkFormat = makeMap('txt,xlsx,docx'); checkFormat('txt')返回true checkFormat('aaa')返回false
 */
export function makeMap(str, lowerCase) {
  const map = Object.create(null);
  if (str) {
    const list = str.toString().split(',');
    for (let i = 0; i < list.length; i++) {
      const key = lowerCase ? list[i].toLowerCase() : list[i];
      map[key] = true;
    }
  }
  return lowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}

/**
 * @auto 刘彬瑜
 * @todo 在全部测点数据中，从机组里匹配出对应的测点名或kks的项
 * @param {Object} crew 全部测点数据里的机组，之所以要传，是为了不用每次都找一次机组
 * @param {String} name 测点名关键词
 * @return {String} kks 测点kks
 * @return {Boolean} type 是否模糊匹配 0精准，1模糊
 */
export function getCharacterFromCrew(crew, name, kks, type) {
  let res = crew.tSdb.find(i => {
    if(name && type) return i.cpName.indexOf(name) != -1;
    if(name && !type) return i.cpName == name;
    if(kks && type) return i.kksCode.indexOf(kks) != -1;
    if(kks && !type) return i.kksCode == kks;
  });
  if(!res) return false; // 如果没有查出匹配的测点，则返回
  if(!res.kksValueR) chatValueHandler(res); // 补数据，只补一次
  return res;
}

/**
 * @auto 刘彬瑜
 * @todo 将测点值处理成信号状态和真实值
 * @param {Object} chat 测点对象
 * @return {Object} chat 处理后的对象
 */
export function chatValueHandler(chat) {
  if(!chat) return chat;
  let val = parseFloat(chat.kksValue?.value); // 数据库返回的值
  let str = val.toString(); // 字符串格式
  if(!val || str === 'NaN') chat.kksValueR = chat.state = 0; // 如果没有值，正常应该是肯定有值的
  // 正常值处理
  else {
    // 如果是无状态测点或者值的长度小于3（因为正常带信号状态的值最少也是1.01）
    if(parseInt(chat.cpType) === 0 || str.length < 3) {
      chat.state = 0;
      chat.kksValueR = val;
    }else{
      chat.state = parseInt(str.substr(-2)); // 信号状态
      chat.kksValueR = parseFloat(str.substr(0, str.length - 2)); // 真实值
    }
  }
  return chat;
}