/*
 * @Description: 根据图片来源匹配压缩
 * @Date: 2021-04-26 17:47:15
 * @LastEditors: gzw
 * @LastEditTime: 2023-05-08 19:54:55
 */
import localStorage from '@/service/localStorage.service';
const CAN_USE_WEBP = 'checkWebp';

// url协议替换
const replaceProtocol = (str = '') => {
  return str.replace('http://', 'https://');
};

// 通过url检测cdn类型, 已处理的会返回false
const getCdnType = function(url, checkProceed = true) {
  const aliReg = new RegExp('img.lkbang.net');
  const qiniuReg = new RegExp('img.mumcooking.com|kdspstatic|appsync');
  const jdReg = new RegExp('360buyimg');
  const hadProceed = new RegExp('imageMogr2|x-oss-process|.dpg|.webp|_jfs'); // 已经处理过的不再处理
  let cdnType = false;
  if (checkProceed && hadProceed.test(url)) {
    cdnType = false;
  } else {
    if (aliReg.test(url)) cdnType = 'ali';
    if (qiniuReg.test(url)) cdnType = 'qiniu';
    if (jdReg.test(url)) cdnType = 'jd';
  }
  return cdnType;
};

// 检测webp是否支持
const canUseWebp = function() {
  return localStorage.get(CAN_USE_WEBP);
};

// webp支持检测
export const checkWebp = function() {
  return new Promise(resolve => {
    const image = new Image();
    image.onload = () => {
      const state = image.width > 0 && image.height > 0;
      localStorage.set(CAN_USE_WEBP, state);
      resolve(state);
    };
    image.onerror = () => {
      localStorage.set(CAN_USE_WEBP, false);
      resolve(false);
    };
    image.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
  });
};

/**
 *
 * 数组join拼接 [url,基础压缩,格式转换,尺寸压缩].join('')
 * 京东的特殊
 *
 */
export const imgMogr = function(url, option = {}) {
  const cdnType = getCdnType(url);
  url = replaceProtocol(url);
  if (!cdnType) return url;
  let { w, h, f } = option;
  if (w) {
    w = w * 2;
  }
  if (h) {
    h = h * 2;
  }

  if (canUseWebp()) f = 'webp';
  const sizeBoth = w && h;
  const sizeMaybe = w || h;
  return {
    ali() {
      return [
        url,
        '?x-oss-process=image/quality,q_70/interlace,1',
        f ? `/format,${f}` : '',
        sizeMaybe
          ? `/resize,${w ? 'w_' + w : ''}${sizeBoth ? ',' : ''}${h ? 'h_' + h : ''},m_fixed`
          : ''
      ].join('');
    },
    qiniu() {
      return [
        url,
        '?imageMogr2/quality/70/interlace/1',
        f ? `/format/${f}` : '',
        sizeMaybe
          ? `/thumbnail/${w || ''}${sizeBoth ? 'x' : ''}${h || ''}${sizeBoth ? '!' : ''}`
          : ''
      ].join('');
    },
    jd() {
      return [
        w && h ? url.replace('jfs', `s${w}x${h}_jfs`) : url,
        '!q70.dpg',
        f === 'webp' ? '.webp' : ''
      ].join('');
    }
  }[cdnType]();
};

// 商品图片压缩polyfill
export function imageMogr4Operation(url, png = false) {
  return imgMogr(url, {
    format: png ? 'png' : 'jpg'
  });
}

// 商品图片压缩polyfill
export function Img2Thumb(url, level = 1) {
  const levelSize = {
    0: {
      width: 220,
      height: 200
    },
    1: {
      width: 360,
      height: 360
    }
  };
  return imgMogr(url, {
    ...levelSize[level]
  });
}

// 指令中通用逻辑提取
const handleTagType = function(el, binding, vnode, reset) {
  if (
    vnode.tag.toLowerCase().indexOf('crimage') > -1 &&
    vnode.child.imgSrc &&
    getCdnType(vnode.child.imgSrc)
  ) {
    const imgSrc = vnode.child.imgSrc;
    if (reset) vnode.child.imgSrc = '';
    vnode.child.imgSrc = imgMogr(imgSrc, binding.value);
  }
};

// 图片处理指令
export const imgMogrDirective = {
  bind(el, binding, vnode) {
    if (el.tagName.toLowerCase() === 'img' && el.src && getCdnType(el.src)) {
      const imgSrc = el.src;
      el.src = '';
      el.src = imgMogr(imgSrc, binding.value);
    }
    handleTagType.call(this, el, binding, vnode, true);
  },
  update(_, binding, vnode) {
    if (vnode.tag.toLowerCase() === 'img' && getCdnType(vnode.elm.src) && vnode.elm.src) {
      vnode.elm.src = imgMogr(vnode.elm.src, binding.value);
    }
    handleTagType.call(this, _, binding, vnode);
  }
};

export const imgMogrVue = {
  install(Vue) {
    // polyfill
    Vue.filter('imageMogr4Operation', imageMogr4Operation);
    // polyfill
    Vue.filter('Img2Thumb', Img2Thumb);
    Vue.filter('imogr', imgMogr);
    Vue.directive('imogr', imgMogrDirective);
    Vue.prototype.$imogr = imgMogr;
  }
};
