import { AxiosResponse } from "axios";

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

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

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

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

/**
 * 判断对象类型
 * @param {*} obj 对象
 */
export function objTypeOf(obj: any): string {
  if (obj === null) return "null";
  if (Array.isArray(obj)) return "array";
  if (obj instanceof Date) return "date";
  if (obj instanceof RegExp) return "regExp";
  if (obj instanceof Blob) return "blob";
  if (typeof obj === "object") return "object";
  return typeof obj;
}

export function blobToText(blob: Blob): Promise<string | ArrayBuffer | null> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsText(blob, "utf-8");
    reader.onload = () => {
      resolve(reader.result);
    };
    reader.onerror = () => {
      reject();
    };
  });
}

/* 日期格式化 */
export const dateFormat = (
  date: any,
  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: any = {
    "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 extractFileName = (str: string) => {
  if (/filename=([^;\s]*)/gi.test(str)) {
    return decodeURIComponent(RegExp.$1);
  }
  return "下载文件";
};

export const download = (res: any, 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: string, filename: string) {
  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);
}

export function urlToBlob(url: string, cb: Function) {
  const xhr = new XMLHttpRequest();
  xhr.open("GET", url, true);
  xhr.responseType = "blob";
  xhr.onload = function () {
    if (xhr.status == 200) {
      cb(URL.createObjectURL(xhr.response));
    }
  };
  xhr.send();
}

export function saveAs(blob: Blob, filename: string) {
  if ((window as any).navigator.msSaveOrOpenBlob) {
    (navigator as any).msSaveBlob(blob, filename);
  } else {
    var link: any = document.createElement("a");
    var body = document.querySelector("body") as HTMLBodyElement;
    link.href = blob;
    link.download = filename;
    link.style.display = "none";
    body.appendChild(link);
    link.click();
    body.removeChild(link);
    window.URL.revokeObjectURL(link.href);
  }
}

export function downloadByCrossUrl(url: string, filename: string) {
  urlToBlob(url, (blob: Blob) => {
    saveAs(blob, filename);
  });
}

export const getRequestParams = (url: string) => {
  const theRequest: any = 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;
};

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

/**
 * 获取随机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("");
}

export function setValueFromObj(targetObj: any, fromObj: any) {
  fromObj = fromObj ? fromObj : {};
  let keys = Object.keys(targetObj);
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    if (fromObj.hasOwnProperty(key)) {
      targetObj[key] = fromObj[key];
    }
  }
  return targetObj;
}

/**
 * 将目标对象中有的属性值与源对象中的属性值合并
 * @param {Object} target 目标对象
 * @param {Object} sources 源对象
 */
export function objAssign<T extends Record<string, any>>(
  target: T,
  sources: Partial<T>
): T {
  const merged = {} as T;
  Object.keys(target).forEach((key) => {
    const propKey = key as keyof T;
    merged[propKey] = Object.prototype.hasOwnProperty.call(sources, propKey)
      ? (sources[propKey] as T[keyof T])
      : target[propKey];
  });

  return merged;
}
/**
 * 使用目标对象中有的属性值修改源对象中的属性值
 * @param {Object} target 目标对象
 * @param {Object} sources 源对象
 */
export function objModifyAssign<T extends Record<string, any>>(
  target: T,
  sources: Partial<T>
): void {
  Object.keys(target).forEach((k: keyof T) => {
    if (Object.prototype.hasOwnProperty.call(sources, k)) {
      target[k] = sources[k] as T[keyof T];
    }
  });
}

/** 获取数组最大数 */
export function maxNum(dataList: number[]): number {
  if (!dataList.length) return 0;
  return Math.max.apply(null, dataList);
}
/** 获取数组最小数 */
export function minNum(dataList: number[]): number {
  if (!dataList.length) return 0;
  return Math.min.apply(null, dataList);
}

export const obj2formData = (obj: Record<string, any>): FormData => {
  const formData = new FormData();
  Object.keys(obj).forEach((key: string) => {
    formData.append(key, obj[key]);
  });
  return formData;
};

export function getFileUrl(url: string) {
  const baseUrl = local.get("baseUrl", "");
  return `${baseUrl}/file/${url}`;
}
