/**
 * 工具方法集合
 */
import { trim, utils, LocationParam } from 'amos-tool';
import { getPropsValue, getToken } from 'amos-designer';

/**
 * 获取去字符串中的变量名称
 * 如 变量${props} 返回 [props]
 * @param {*} str
 */
function getExecStrs(str) {
  if (str && utils.isString(str)) {
    const reg = /\{(.+?)\}/g;
    const list = [];
    let result = null;
    let defaultValue = '';
    let key = null;
    do {
      result = reg.exec(str);
      if (result && result[1]) {
        if (result[1].includes('||')) {
          const keyAndDefault = result[1].split('||');
          key = keyAndDefault[1].trim();
          defaultValue = keyAndDefault[1].trim();
        } else {
          key = result[1];
        }
        list.push({ key, defaultValue, content: result[1] });
      }
    } while (result);
    return list;
  } else {
    return [];
  }
}

export function getValue(data, value) {
  if (utils.isString(value)) {
    if (value.includes('{')) {
      let variables = getExecStrs(value);
      let resValue = value;
      variables.forEach(e => {
        let { key, defaultValue, content } = e || {};
        let _value = getPropsValue(data, key, defaultValue);
        resValue = resValue.replace(`{${content}}`, _value);
      });
      return resValue;
    } else {
      return getPropsValue(data, value);
    }
  } else if (utils.isFunction(value)) {
    return value(data);
  } else {
    return value;
  }
}
/**
 *
 * @param {*} param
 * @param {*} key
 * @param {*} encode
 */
export const urlEncode = function (param, key, encode) {
  if (param == null) {
    return '';
  }
  let paramStr = '';
  let t = typeof param;

  if (t === 'string' || t === 'number' || t === 'boolean') {
    paramStr += `&${key}=${encode == null || encode ? encodeURIComponent(param) : param}`;
  } else {
    let keys = Object.keys(param);
    keys && keys.forEach(item => {
      let k = key == null ?
        item : key + (param instanceof Array ? `[${item}]` : `.${item}`);
      if (param[item] != null && param[item] !== '') {
        paramStr += urlEncode(param[item], k, encode);
      }
    });
  }
  return paramStr;
};

/**
 * 判断当前是否全屏
 */
export const isFullscreenForNoScroll = () => {
  let explorer = window.navigator.userAgent.toLowerCase();
  if (explorer.indexOf('chrome') > 0) {// webkit
    if (document.body.scrollHeight === window.screen.height && document.body.scrollWidth === window.screen.width) {
      return true;
    } else {
      return false;
    }
  } else {// IE 9+  fireFox
    if (window.outerHeight === window.screen.height && window.outerWidth === window.screen.width) {
      return true;
    } else {
      return false;
    }
  }
};
/**
 * 全屏
* @param {*} dom 要全屏的dom节点
 */
export const fullScreen = (dom) => {
  const element = dom ? dom : document.documentElement;
  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 exitFullscreen = () => {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
};
/**
 * 全屏与退出全屏之间切换
 */
export const switchFullScreen = () => {
  if (isFullscreenForNoScroll()) {
    exitFullscreen();
  } else {
    fullScreen();
  }
};
/**
 * 判断是否点击空白处
 * 通过样式名判断
 * @param {*} callback 没找到则调用回调函数
 * @param {array} filter 样式名数组
 */
export const isClickBlankByClass = (callback, filter) => {
  return event => {
    const path = event.nativeEvent.path;
    if (path.some(e => e.className === event.target.className)) {
      if (!path.some(e => filter.some(item => {
        let flag = false;
        e.classList && e.classList.length > 0 && e.classList.forEach(i => {
          if (i === item) {
            flag = true;
          }
        });
        return flag;
      })
      )) {
        callback(event);
      }
    }
  };
};
/**
 * 下载图片（根据图片地址）
 * @param {*} data
 * @param {*} name
 * @param {*} width
 * @param {*} height
 */
export const downloadIamge = (data, name, width, height) => {
  let image = new Image();
  image.onload = function () {
    let canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;

    let context = canvas.getContext('2d');
    context.drawImage(image, 0, 0, width, height);
    let url = canvas.toDataURL('image/png');
    // 生成一个a元素
    let a = document.createElement('a');
    // 创建一个单击事件
    let event = new MouseEvent('click');

    // 将a的download属性设置为我们想要下载的图片名称，若name不存在则使用‘下载图片名称’作为默认名称
    a.download = name || '下载图片名称';
    // 将生成的URL设置为a.href属性
    a.href = url;

    // 触发a的单击事件
    a.dispatchEvent(event);
  };
  image.src = data;
};
/**
 * 过滤对象中字符串的前后空格
 * @param {*} form
 */
export const trimObjectData = (form) => {
  for (let key in form) {
    if ((typeof form[key] === 'string') && form[key].constructor === String) {
      form[key] = trim(form[key]);
    }
  }
  return form;
};

/**
 * 用于遍历树形结构数据
 * @param {*} list
 * @param {*} childName
 */
export const recursive = function (list, childName = 'children') {
  class recursiveClass {
    constructor(_list, _childName) {
      this.list = _list || [];
      this.childName = _childName;
    }

    some(callback) {
      const func = arr => {
        return arr.some((e, index) => {
          const flag = callback(e, index);
          if (flag) {
            return flag;
          } else {
            if (e[this.childName] && e[this.childName].length > 0) {
              return func(e[this.childName]);
            }
          }
          return false;
        });
      };
      return func(this.list);
    }

    find(callback) {
      let obj = null;
      const func = (arr, parent) => {
        return arr.find((e, index) => {
          const flag = callback(e, index, parent);
          if (flag) {
            obj = e;
            return flag;
          } else {
            if (e[this.childName] && e[this.childName].length > 0) {
              return func(e[this.childName], e);
            }
          }
          return false;
        });
      };
      func(this.list, {});
      return obj;
    }

    findParent(callback) {
      let obj = null;
      const func = (arr, parent) => {
        return arr.find((e, index) => {
          const flag = callback(e, index, parent);
          if (flag) {
            obj = parent;
            return flag;
          } else {
            if (e[this.childName] && e[this.childName].length > 0) {
              return func(e[this.childName], e);
            }
          }
          return false;
        });
      };
      func(this.list, {});
      return obj;
    }

    findIndex(callback) {
      let resIndex = -1;
      const func = (arr, parent) => {
        return arr.find((e, index) => {
          const flag = callback(e, index, parent);
          if (flag) {
            resIndex = index;
            return flag;
          } else {
            if (e[this.childName] && e[this.childName].length > 0) {
              return func(e[this.childName], e);
            }
          }
          return false;
        });
      };
      func(this.list, {});
      return resIndex;
    }

    filter(callback) {
      const func = (arr, parent) => {
        return arr.filter((e, index) => {
          const flag = callback(e, index, parent);
          if (flag) {
            if (e[this.childName] && e[this.childName].length > 0) {
              e[this.childName] = func(e[this.childName], e);
            }
          }
          return flag;
        });
      };
      return func(this.list, {});
    }

    search(callback) {
      const func = (arr, parent) => {
        return arr.filter((e, index) => {
          let flag = callback(e, index, parent);
          if (e[this.childName] && e[this.childName].length > 0) {
            e[this.childName] = func(e[this.childName], e);
            if (e[this.childName] && e[this.childName].length > 0) {
              flag = true;
            }
          }
          return flag;
        });
      };
      return func(this.list, {});
    }

    map(callback) {
      const func = (arr, parent) => {
        return arr.map((e, index) => {
          const node = callback(e, index, parent);
          if (node) {
            e = node;
          }
          if (e[this.childName] && e[this.childName].length > 0) {
            e[this.childName] = func(e[this.childName], e);
          }
          return e;
        });
      };
      return func(this.list, {});
    }
  }

  return new recursiveClass(list, childName);
};

const deep = (val) => {
  if (val.length > 0) {
    val.forEach((item, index, array) => {
      let children = item.children;
      if (children) {
        if (children.length === 0) {
          delete item.children;
        } else {
          deep(children);
        }
      }
    });
  }
};

/**
 * 遍历循环移除空子节点数据
 * @param val
 */
export const deepRemove = deep;


/**
 * 格式化数据
 * @param arr 传入数组
 * @returns 格式化后数据
 */
export const formatterCategory = arr => {
  let data = [];
  if (arr.length > 0) {
    arr.forEach((item, i) => {
      data.push({ label: item.name, value: item.id, children: [] });
      if (item.children.length > 0) {
        data[i].children = this.formatterCategory(item.children);
      }
    });
  }
  return data;
};

/**
 * div上同时包含单双击事件时解决双击事件不起效问题
 * @param {*} singleClick 单击事件
 * @param {*} doubleClick 双击事件
 */
export const singleAndDoubleClick = function (singleClick, doubleClick) {
  let timer = null;
  let prevent = false;
  const delay = 300;
  return {
    onClick: e => {
      timer = setTimeout(() => {
        if (!prevent) {
          singleClick && singleClick(e);
        }
        prevent = false;
      }, delay);
    },
    onDoubleClick: e => {
      clearTimeout(timer);
      prevent = true;
      doubleClick && doubleClick(e);
    }
  };
};

/**
 * 计算百分比
 * @param {number} num 数量
 * @param {number} total 总数
 * @return {sring} 百分百 如10%
 */
export const percentage = function (num, total) {
  const hrun = 100;
  return `${Math.round(num / total * hrun)}%`;
};

const timeCovert = 60;

/**
 * 时间秒速转换成时分秒
 * @param {*} result
 */
export const secondToDate = (result) => {
  const ten = 10;
  const h = Math.floor(result / (timeCovert * timeCovert)) < ten ?
    `0${Math.floor(result / (timeCovert * timeCovert))}` : Math.floor(result / (timeCovert * timeCovert));
  const m = Math.floor(result / timeCovert % timeCovert) < ten ?
    `0${Math.floor(result / timeCovert % timeCovert)}` : Math.floor(result / timeCovert % timeCovert);
  const s = Math.floor(result % timeCovert) < ten ? `0${Math.floor(result % timeCovert)}` : Math.floor(result % timeCovert);
  return [h, m, s];
};

export const jsonObjDeepClone = jsonObj => {
  return JSON.parse(JSON.stringify(jsonObj));
};

/**
 * 补全token
 * @param {*} url
 * @param {*} token
 */
export const completeToken = (url) => {
  const searchToken = LocationParam.getParameter(url, 'token');
  if (utils.isEmpty(searchToken)) {
    url = LocationParam.completeParam({ token: getToken() }, url);
  }
  if (!utils.isUrl(url)) {
    let href = window.location.href;
    let http = href.match(/^(http:\/\/).+?(?=\/)/g);
    url = url.indexOf('/') === 0 ? `${http}${url}` : `${http}/${url}`;
  }
  return url;
};
/**
 * url参数对象特殊字符转码
 * @param {*} params
 */
export function objEncodeURI(params) {
  Object.keys(params).forEach(item => {
    let nowData = params[item];
    try {
      params[item] = encodeURIComponent(decodeURIComponent(nowData));
    } catch (err) {
      const reg = new RegExp(/\%/, 'g');
      params[item] = encodeURIComponent(decodeURIComponent(nowData.replace(reg, '%25')));
    }
  });
  return params;
}

// repeatClick(this.onClick)
let isClick = false;

export const repeatClick = (callback) => {
  return (...args) => {
    if (isClick) {
      return;
    }
    isClick = true;
    const data = callback(...args);
    if (data instanceof Promise) {
      data.finally(() => {
        isClick = false;
      });
    }
    isClick = false;
  };
};
