import { cloneDeep } from 'lodash';
import { useUserStore } from '@/store';
import { DialogPlugin } from 'tdesign-vue-next';

export const extractFileName = (str) => {
  if (/filename=([^;\s]*)/gi.test(str)) {
    return decodeURIComponent(RegExp.$1);
  }
  return '下载文件';
};

const typeColor = (type = 'default') => {
  let color = '';
  switch (type) {
    case 'default':
      color = '#35495E';
      break;
    case 'primary':
      color = '#3488ff';
      break;
    case 'success':
      color = '#43B883';
      break;
    case 'warning':
      color = '#e6a23c';
      break;
    case 'danger':
      color = '#f56c6c';
      break;
    default:
      break;
  }
  return color;
};

/**
 * LocalStorage
 */
export const local = {
  set(table, settings) {
    const _set = JSON.stringify(settings);
    return localStorage.setItem('sop_' + table, _set);
  },
  get(table) {
    let data = localStorage.getItem('sop_' + table);
    try {
      data = JSON.parse(data);
    } catch (err) {
      return null;
    }
    return data;
  },
  remove(table) {
    return localStorage.removeItem('sop_' + table);
  },
  clear() {
    return localStorage.clear();
  },
};

/**
 * SessionStorage
 */
export const session = {
  set(table, settings) {
    const _set = JSON.stringify(settings);
    return sessionStorage.setItem('sop_' + table, _set);
  },
  get(table) {
    let data = sessionStorage.getItem('sop_' + table);
    try {
      data = JSON.parse(data);
    } catch (err) {
      return null;
    }
    return data;
  },
  remove(table) {
    return sessionStorage.removeItem('sop_' + table);
  },
  clear() {
    return sessionStorage.clear();
  },
};

export const clear = () => {
  localStorage.clear();
  sessionStorage.clear();
};

/**
 * CookieStorage
 */
export const cookie = {
  set(name, value, config = {}) {
    const cfg = {
      expires: null,
      path: null,
      domain: null,
      secure: false,
      httpOnly: false,
      ...config,
    };
    let cookieStr = `${name}=${escape(value)}`;
    if (cfg.expires) {
      const exp = new Date();
      exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000);
      cookieStr += `;expires=${exp.toGMTString()}`;
    }
    if (cfg.path) {
      cookieStr += `;path=${cfg.path}`;
    }
    if (cfg.domain) {
      cookieStr += `;domain=${cfg.domain}`;
    }
    document.cookie = cookieStr;
  },
  get(name) {
    const arr = document.cookie.match(new RegExp(`(^| )${name}=([^;]*)(;|$)`));
    if (arr != null) {
      return unescape(arr[2]);
    }
    return null;
  },
  remove(name) {
    const exp = new Date();
    exp.setTime(exp.getTime() - 1);
    document.cookie = `${name}=;expires=${exp.toGMTString()}`;
  },
};

/* Fullscreen */
export const screen = (element) => {
  const isFull = !!(
    document.webkitIsFullScreen ||
    document.mozFullScreen ||
    document.msFullscreenElement ||
    document.fullscreenElement
  );
  if (isFull) {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    }
  } else if (element.requestFullscreen) {
    element.requestFullscreen();
  } else if (element.msRequestFullscreen) {
    element.msRequestFullscreen();
  } else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen();
  }
};
/* 百分比值 */
export const division = (a, b, fixed = 2) => {
  if (b == 0) return '0.00';
  return ((a * 100) / b).toFixed(fixed);
};
/* 复制对象 */
export const objCopy = (obj) => {
  if (obj === undefined) {
    return undefined;
  }
  return JSON.parse(JSON.stringify(obj));
};

export const generateId = function () {
  return Math.floor(
    Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000
  );
};

/* 日期格式化 */
export const dateFormat = (
  date,
  fmt = 'yyyy/MM/dd HH:mm:ss',
  isDefault = '-'
) => {
  if (!date) {
    return '-';
  }
  if (date.toString().length === 10) {
    date *= 1000;
  }
  date = new Date(date);

  if (date.valueOf() < 1) {
    return isDefault;
  }
  const o = {
    'M+': date.getMonth() + 1, // 月份
    'd+': date.getDate(), // 日
    'H+': date.getHours(), // 小时
    'm+': date.getMinutes(), // 分
    's+': date.getSeconds(), // 秒
    'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
    'S': date.getMilliseconds(), // 毫秒
  };
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(
      RegExp.$1,
      `${date.getFullYear()}`.substr(4 - RegExp.$1.length)
    );
  }
  for (const 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;
};

/* 千分符 */
export const groupSeparator = (num) => {
  num += '';
  if (!num.includes('.')) {
    num += '.';
  }
  return num
    .replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
      return `${$1},`;
    })
    .replace(/\.$/, '');
};

export const capsule = (title, info, type = 'primary') => {
  console.log(
    `%c ${title} %c ${info} %c`,
    'background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;',
    `background:${typeColor(
      type
    )}; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff;`,
    'background:transparent'
  );
};

export const download = (res, downName = '') => {
  const aLink = document.createElement('a');
  let fileName = downName;
  let blob = res; // 第三方请求返回blob对象

  // 通过后端接口返回
  if (res.headers && res.data) {
    blob = new Blob([res.data], {
      type: res.headers['content-type'].replace(';charset=utf8', ''),
    });
    if (!downName) {
      fileName = extractFileName(res.headers?.['content-disposition']);
    }
  }

  aLink.href = URL.createObjectURL(blob);
  // 设置下载文件名称
  aLink.setAttribute('download', fileName);
  document.body.appendChild(aLink);
  aLink.click();
  document.body.removeChild(aLink);
  URL.revokeObjectURL(aLink.href);
};

/**
 * 下载url
 * @param {String} url 文件下载地址
 * @param {String}} filename 文件名
 */
export function downloadByUrl(url, filename) {
  const tempLink = document.createElement('a');
  tempLink.style.display = 'none';
  tempLink.href = url;
  const fileName = filename || url.split('/').pop().split('?')[0];
  tempLink.setAttribute('download', fileName);
  if (tempLink.download === 'undefined') {
    tempLink.setAttribute('target', '_blank');
  }
  document.body.appendChild(tempLink);
  tempLink.click();
  document.body.removeChild(tempLink);
  window.URL.revokeObjectURL(url);
}

/**
 * 对象转url参数
 * @param {*} data
 * @param {*} isPrefix
 */
export const httpBuild = (data, isPrefix = false) => {
  const prefix = isPrefix ? '?' : '';
  const _result = [];
  for (const key in data) {
    const value = data[key];
    // 去掉为空的参数
    if (['', undefined, null].includes(value)) {
      continue;
    }
    if (value.constructor === Array) {
      value.forEach((_value) => {
        _result.push(
          `${encodeURIComponent(key)}[]=${encodeURIComponent(_value)}`
        );
      });
    } else {
      _result.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
    }
  }

  return _result.length ? prefix + _result.join('&') : '';
};

export const getRequestParams = (url) => {
  const theRequest = new Object();
  if (url.indexOf('?') != -1) {
    const params = url.split('?')[1].split('&');
    for (let i = 0; i < params.length; i++) {
      const param = params[i].split('=');
      theRequest[param[0]] = decodeURIComponent(param[1]);
    }
  }
  return theRequest;
};

export const getTreeList = (oldDataList, sortField = '') => {
  if (!Array.isArray(oldDataList)) {
    throw new TypeError(`${oldDataList}不是数组`);
  }
  const dataList = cloneDeep(oldDataList);
  const formatObj = dataList.reduce((pre, cur) => {
    return { ...pre, [cur.id]: cur };
  }, {});
  const sortArray = sortField
    ? dataList.sort((a, b) => a.sort - b.sort)
    : dataList;
  const formatArray = sortArray.reduce((arr, cur) => {
    const pid = cur.parentId ? cur.parentId : '-1';
    const parent = formatObj[pid];
    if (parent) {
      parent.children ? parent.children.push(cur) : (parent.children = [cur]);
    } else {
      arr.push(cur);
    }
    return arr;
  }, []);
  return formatArray;
};

/**
 * 将一维数组转换为二维数组
 * @param {*} arr
 * @returns
 */
export const toSecondFloorArray = (arr) => {
  if (!Array.isArray(arr)) {
    throw new TypeError(`${arr}不是数组`);
  }
  const newArr = arr.reduce((initArr, item, index) => {
    if (index % 2 == 0) {
      initArr.push([item]);
    } else {
      initArr[initArr.length - 1].push(item);
    }
    return initArr;
  }, []);
  return newArr;
};

/**
 * 字典数据转成option list
 * @param {Object} data 字典数据
 * @returns list
 */
export const dictToOptionList = (data) => {
  return Object.keys(data).map((k) => {
    const kstr = typeof k === 'number' ? k : k + '';
    return { value: kstr, label: data[k] };
  });
};

/**
 * 判断用户的权限集里有没有
 * @param {*} key
 * @returns
 */
export const hasPerm = (key) => {
  const userStore = useUserStore();
  return userStore.finePermissionIds.includes(key);
};

/**
 * 获取随机code,默认获取16位
 * @param {Number} len 推荐8的倍数
 *
 */
export function randomCode(len = 16) {
  if (len <= 0) return;
  let steps = Math.ceil(len / 8);
  let stepNums = [];
  for (let i = 0; i < steps; i++) {
    let ranNum = Math.random().toString(32).slice(-8);
    stepNums.push(ranNum);
  }

  return stepNums.join('');
}

/**
 * 判断对象类型
 * @param {*} obj 对象
 */
export function objTypeOf(obj) {
  const toString = Object.prototype.toString;
  const map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object',
    '[object Blob]': 'blob',
  };
  return map[toString.call(obj)];
}

/**
 *  获取时间长度文字
 * @param {Number} timeNumber 时间数值，单位：毫秒
 */
export function timeNumberToText(timeNumber) {
  const DAY_TIME = 24 * 60 * 60 * 1000;
  const HOUR_TIME = 60 * 60 * 1000;
  const MINUTE_TIME = 60 * 1000;
  const SECOND_TIME = 1000;
  let [day, hour, minute, second] = [0, 0, 0, 0];
  let residueTime = timeNumber;

  if (residueTime >= DAY_TIME) {
    day = Math.floor(residueTime / DAY_TIME);
    residueTime -= day * DAY_TIME;
    day += '天';
  }
  if (residueTime >= HOUR_TIME) {
    hour = Math.floor(residueTime / HOUR_TIME);
    residueTime -= hour * HOUR_TIME;
    hour += '小时';
  }
  if (residueTime >= MINUTE_TIME) {
    minute = Math.floor(residueTime / MINUTE_TIME);
    residueTime -= minute * MINUTE_TIME;
    minute += '分钟';
  }
  if (residueTime >= SECOND_TIME) {
    second = Math.round(residueTime / SECOND_TIME);
    second += '秒';
  }

  return [day, hour, minute, second].filter((item) => !!item).join('');
}

//判断两个对象是否相等
export function isEqual(objA, objB) {
  //相等
  if (objA === objB) return objA !== 0 || 1 / objA === 1 / objB;
  //空判断
  if (objA == null || objB == null) return objA === objB;
  //类型判断
  if (
    Object.prototype.toString.call(objA) !==
    Object.prototype.toString.call(objB)
  )
    return false;

  switch (Object.prototype.toString.call(objA)) {
    case '[object RegExp]':
    case '[object String]':
      //字符串转换比较
      return '' + objA === '' + objB;
    case '[object Number]':
      //数字转换比较,判断是否为NaN
      if (+objA !== +objA) {
        return +objB !== +objB;
      }

      return +objA === 0 ? 1 / +objA === 1 / objB : +objA === +objB;
    case '[object Date]':
    case '[object Boolean]':
      return +objA === +objB;
    case '[object Array]':
      //判断数组
      for (let i = 0; i < objA.length; i++) {
        if (!isEqual(objA[i], objB[i])) return false;
      }
      return true;
    case '[object Object]':
      //判断对象
      let keys = Object.keys(objA);
      for (let i = 0; i < keys.length; i++) {
        if (!isEqual(objA[keys[i]], objB[keys[i]])) return false;
      }

      keys = Object.keys(objB);
      for (let i = 0; i < keys.length; i++) {
        if (!isEqual(objA[keys[i]], objB[keys[i]])) return false;
      }

      return true;
    default:
      return false;
  }
}

export const appUpdateObserver = () => {
  window.addEventListener(
    'error',
    (e) => {
      if (e.target.localName === 'script' || e.target.localName === 'link') {
        DialogPlugin({
          header: '提示',
          body: `检测到系统功能已升级，点击"确定"自动刷新获取更新`,
          confirmBtn: '确定',
          cancelBtn: null,
          onConfirm: async () => {
            if ('caches' in window) {
              caches
                .keys()
                .then((cacheNames) => {
                  const arr = cacheNames.map((cacheName) => {
                    return caches.delete(cacheName);
                  });
                  return arr;
                })
                .then(() => {
                  location.reload();
                });
            } else {
              location.reload();
            }
          },
        });
      }
      e.preventDefault();
    },
    true
  );
};
