/**
 * @Description: canvas 简单的水印工具
 * @Author: CcSimple
 * @Github: https://github.com/CcSimple
 */

/**
 * @Description: 时间格式化
 * @param date
 * @param format
 * @returns {string|null}
 */
function timeFormat(date, format = 'YYYY-MM-DD') {
  if (!date) return null;
  if (typeof date === 'number') {
    date = new Date(date);
  }
  const year = date.getFullYear();
  const month = date.getMonth();
  const day = date.getDate();
  const hours24 = date.getHours();
  const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
  const minutes = date.getMinutes();
  const seconds = date.getSeconds();
  const dd = t => `0${t}`.slice(-2);
  const map = {
    YYYY: year,
    MM: dd(month + 1),
    MMMM: `${month + 1}月`,
    M: month + 1,
    DD: dd(day),
    D: day,
    HH: dd(hours24),
    H: hours24,
    hh: dd(hours),
    h: hours,
    mm: dd(minutes),
    m: minutes,
    ss: dd(seconds),
    s: seconds
  };
  return format.replace(/Y+|M+|D+|H+|h+|m+|s+|S+|Q/g, str => String(map[str]));
}

// 水印参数
const defaultOption = {
  id: 'watermark', // 水印id
  watch: false,
  content: 'vue-plugin-hiprint', // 水印内容
  container: '.hiprint-printPaper', // 水印容器
  width: 200, // 水印宽度
  height: 200, // 水印高度
  textAlign: 'center', // 水印文字水平对齐方式
  textBaseline: 'middle', // 水印文字垂直对齐方式
  fontSize: '14px', // 水印文字大小
  fontFamily: 'Microsoft Yahei', // 水印文字字体
  fillStyle: 'rgba(184, 184, 184, 0.3)', // 水印文字颜色
  rotate: 25,// 水印文字旋转角度
  timestamp: false, // 是否显示时间戳
  format: 'YYYY-MM-DD HH:mm', // 时间戳格式
  zIndex: 0
};

// 监听器
let observerMap = {};

/**
 * @Description: 创建水印
 * @param param
 * @private
 */
function _createWatermark(param) {
  const {
    id,
    watch,
    content,
    container,
    width,
    height,
    textAlign,
    textBaseline,
    fontSize,
    fontFamily,
    fillStyle,
    rotate,
    timestamp,
    format,
    zIndex
  } = param;

  observerMap[id] = {
    wmMo: null, // MutationObserver
    wmTimer: null // timestamp
  }

  const canvas = document.createElement('canvas');
  canvas.setAttribute('width', `${width}px`);
  canvas.setAttribute('height', `${height}px`);

  let containerDom = typeof container === 'string' ? document.querySelector(container) : container;

  const ctx = canvas.getContext('2d');
  ctx.textAlign = textAlign;
  ctx.textBaseline = textBaseline;
  ctx.font = `${fontSize} ${fontFamily}`;
  ctx.fillStyle = fillStyle;
  ctx.translate(width / 2, height / 2);
  ctx.rotate(-(Math.PI / 180) * rotate);
  ctx.fillText(`${content}`, 0, 0);
  timestamp && ctx.fillText(`${timeFormat(new Date(), format)}`, 0, parseInt(fontSize) + 5);

  let __vm = containerDom.querySelector('.__vm__' + id);
  const watermarkDiv = __vm || document.createElement('div');
  const withHeightStr = containerDom.getAttribute('style');
  const styleStr = `position:absolute;user-select:none;top:0;left:0;${withHeightStr};z-index:${zIndex};pointer-events:none !important;background-repeat:repeat;background-image:url('${canvas.toDataURL()}')`;

  watermarkDiv.setAttribute('style', styleStr);
  watermarkDiv.classList.add('__vm__' + id);

  if (!__vm) {
    containerDom.insertBefore(watermarkDiv, containerDom.firstChild);
  }

  if (watch) {
    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    if (MutationObserver) {
      observerMap[id]["wmMo"] = new MutationObserver((e) => {
        let change = e.some(item => item.target.className == containerDom.className && item.type == 'attributes');
        __vm = containerDom.querySelector('.__vm__' + id);
        if ((__vm && __vm.getAttribute('style') !== styleStr) || !__vm || change) {
          // 避免一直触发
          observerMap[id]["wmMo"].disconnect();
          observerMap[id]["wmMo"] = null;
          delete observerMap[id]["wmMo"];
          _createWatermark(param);
        }
      });
      observerMap[id]["wmMo"].observe(containerDom, {
        attributes: true, subtree: true, childList: true
      });
    }
  }

  if (format) {
    let timeout = 1000 * 60 * 60 * 24;
    if (format.includes('s')) {
      timeout = 1000;
    } else if (format.includes('m')) {
      timeout = 1000 * 60;
    } else if (format.includes('h') || format.includes('H')) {
      timeout = 1000 * 60 * 60;
    }

    observerMap[id]["wmTimer"] = window.setTimeout(() => {
      // 触发 MutationObserver
      watermarkDiv.style.bottom = '0';
    }, timeout);
  }
}

/**
 * @Description: 销毁水印
 */
const destroyWatermark = function (options) {
  const {
    id,
    watch,
    container,
  } = options;
  if (watch) {
    let containerDom = typeof container === 'string' ? document.querySelector(container) : container;
    // 监听器关闭
    if (observerMap[id]) {
      observerMap[id]["wmMo"] && observerMap[id]["wmMo"].disconnect();
      observerMap[id]["wmMo"] = null;
      observerMap[id]["wmTimer"] && window.clearTimeout(observerMap[id]["wmTimer"]);
      observerMap[id]["wmTimer"] = null;
      delete observerMap[id];
    }
    // 删除水印元素
    const __vm = containerDom.querySelector('.__vm__' + id);
    __vm && __vm.parentNode.removeChild(__vm);
  }
}

/**
 * @Description: 创建水印
 * @param option
 */
const createWatermark = function (option) {
  let options = Object.assign({}, defaultOption, option);
  destroyWatermark(options);
  _createWatermark(options);
}

// 暴露接口
export default {
  createWatermark, destroyWatermark
}
