/**
 * 字符串类
 */
export class StringManager {
  constructor() {}

  /**
   * 获取uuid
   * @param {Number} len uuid的长度
   * @param {Boolean} first 默认的首字母
   * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
   */
  uuid = (len = 32, first = "", radix = null) => {
    const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
    const uuid = []
    radix = radix || chars.length

    if (len) {
      // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
      for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
    } else {
      let r
      // rfc4122标准要求返回的uuid中,某些位为固定的字符
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
      uuid[14] = '4'

      for (let i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | Math.random() * 16
          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
        }
      }
    }
    // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
    if (first != "") {
      uuid.shift()
      return `${first}${uuid.join('')}`
    }
    return uuid.join('')
  }

  /**
   * @description 去除空格
   * @param String str 需要去除空格的字符串
   * @param String pos both(左右)|left|right|all 默认both
   */
  trim = (str, pos = 'both') => {
    str = String(str)
    if (pos == 'both') {
      return str.replace(/^\s+|\s+$/g, '')
    }
    if (pos == 'left') {
      return str.replace(/^\s*/, '')
    }
    if (pos == 'right') {
      return str.replace(/(\s*$)/g, '')
    }
    if (pos == 'all') {
      return str.replace(/\s+/g, '')
    }
    return str
  }

  /**
   * 验证字符串
   */
  isString = (str) => {
    return typeof str === 'string'
  }

  /**
   * 验证是否包含某个值
   */

  isContains = (str1, str2) => {
    return str1.indexOf(str2) >= 0
  }

  /**
   * 是否json字符串
   */
  isJsonString = (str) => {
    if (typeof str === 'string') {
      try {
        const obj = JSON.parse(str)
        if (typeof obj === 'object' && obj) {
          return true
        }
        return false
      } catch (e) {
        return false
      }
    }
    return false
  }

  /**
   * 字节格式化
   */
  sizeFormat = (size) => {
    if (size < 1024) {
      return size + 'B';
    } else if (size < (1024 * 1024)) {
      var temp = size / 1024;
      temp = temp.toFixed(2);
      return temp + 'KB';
    } else if (size < (1024 * 1024 * 1024)) {
      var temp = size / (1024 * 1024);
      temp = temp.toFixed(2);
      return temp + 'MB';
    } else {
      var temp = size / (1024 * 1024 * 1024);
      temp = temp.toFixed(2);
      return temp + 'GB';
    }
  }

  /**参数说明：
   * 根据长度截取先使用字符串，超长部分追加… 
   * str 对象字符串 
   * len 目标字节长度 
   * 返回值： 处理结果字符串 
   */
  substring = (str, len = 10, end = "...") => {
    if (str) {
      if (str.length <= len) {
        return str;
      }
      let strlen = 0;
      let s = "";
      for (let i = 0; i < str.length; i++) {
        s = s + str.charAt(i);
        strlen = strlen + 1;
        if (strlen > len) {
          return s.substring(0, s.length - 1) + end;
        }
      }
      return s;
    } else {
      return '';
    }
  }

  /**
   * 隐藏字符
   * @param str 原始字符串
   * @param starCount 显示隐藏字符的个数
   * @param prevCount 开始显示的字符串个数
   * @param endCount 结束显示的字符串个数
   */
  hideString = (str, starCount = 4, prevCount = 3, endCount = 4) => {
    if (!str) {
      return "";
    }
    if (str <= prevCount || str.length <= (prevCount + endCount)) {
      return str;
    }

    let starStr = "******************************";
    let startStr = str.substr(0, prevCount);
    let endStr = str.substr(str.length - endCount, endCount);

    return startStr + starStr.substr(0, starCount) + endStr;
  }

  /**
   * 字符串反转
   */
  reverse(str) {
    return str.split('').reverse().join('');
  }

  /**
   * 随机字符串
   * @param length  生成的长度
   * @param num  是否包含数字
   * @param lowerLetters  是否包含小写字母
   * @param upperLetters  是否包含大写字母
   * @param specialCharacters  是否包含特殊字符
   */
  random = (length, num = true, lowerLetters = true, upperLetters = true, specialCharacters = true) => {
    // 数字
    let numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    // 小写字母
    let lowers = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    // 大写字母
    let uppers = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    // 特殊字符
    let specials = ['#', '!', '@', '$', '%', '^', '&'];
    // 可用的字符集合
    let values = [];
    if (num) {
      values = values.concat(numbers);
    }
    if (lowerLetters) {
      values = values.concat(lowers);
    }
    if (upperLetters) {
      values = values.concat(uppers);
    }
    if (specialCharacters) {
      values = values.concat(specials);
    }
    // 返回值
    let returnArr = [];
    if (length > 0) {
      for (let i = 0; i < length; i++) {
        // 去除一个随机值
        let index = Math.floor(Math.random() * values.length);
        returnArr.push(values[index]);
      }
    }

    return returnArr.join("");
  }

  /**
   * 转大写
   */
  toUpper = (str) => {
    if (this.isString(str)) {
      return str.toUpperCase()
    }
    return str;
  }

  /**
   * 转小写
   */
  toLower = (str) => {
    if (this.isString(str)) {
      return str.toLowerCase()
    }
    return str;
  }

  /**
   * 下划线转驼峰
   */
  underlineToHump = (str) => {
    return str.replace(/\_(\w)/g, function(all, letter) {
      return letter.toUpperCase();
    });
  }

  /**
   * 驼峰转下划线
   */
  humpToUnderline = (str) => {
    return str.replace(/([A-Z])/g, "_$1").toLowerCase();
  }

  /**
   *@param {string} url 完整的URL地址
   *@returns {object} 自定义的对象
   *@description 用法示例：var myURL = parseURL('http://abc.com:8080/dir/index.html?id=255&m=hello#top');
   myURL.file='index.html'
   myURL.hash= 'top'
   myURL.host= 'abc.com'
   myURL.query= '?id=255&m=hello'
   myURL.params= Object = { id: 255, m: hello }
   myURL.path= '/dir/index.html'
   myURL.segments= Array = ['dir', 'index.html']
   myURL.port= '8080'
   myURL.protocol= 'http'
   myURL.source= 'http://abc.com:8080/dir/index.html?id=255&m=hello#top'
   */
  parseUrl = (url) => {
    var a = document.createElement('a');
    a.href = url;
    return {
      source: url,
      protocol: a.protocol.replace(':', ''),
      host: a.hostname,
      port: a.port,
      query: a.search,
      params: (function() {
        var ret = {},
          seg = a.search.replace(/^\?/, '').split('&'),
          len = seg.length,
          i = 0,
          s;
        for (; i < len; i++) {
          if (!seg[i]) {
            continue;
          }
          s = seg[i].split('=');
          ret[s[0]] = s[1];
        }
        return ret;
      })(),
      file: (a.pathname.match(/\/([^\/?#]+)$/i) || [, ''])[1],
      hash: a.hash.replace('#', ''),
      path: a.pathname.replace(/^([^\/])/, '/$1'),
      relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [, ''])[1],
      segments: a.pathname.replace(/^\//, '').split('/')
    };
  }

  /**
   * 将字符串转换为16进制
   */
  stringToHex = (str, isUrlEncode = true) => {
    let val = "";
    if (isUrlEncode) {
      // 如果包含特殊字符或中文先转换
      str = encodeURIComponent(str);
    }
    for (let i = 0; i < str.length; i++) {
      val += str.charCodeAt(i).toString(16);
    }
    return val;
  }

  /**
   * 十六进制转换为字符串
   * @param {*} str 
   */
  hexToString = (str, isUrlDecode = true) => {
    var val = "",
      len = str.length / 2;
    for (var i = 0; i < len; i++) {
      val += String.fromCharCode(parseInt(str.substr(i * 2, 2), 16));
    }
    if (!isUrlDecode) {
      return val;
    }
    // 转换结果
    return decodeURIComponent(val);
  }
}