import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _regeneratorRuntime from "@babel/runtime/regenerator";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { createBEM } from '@zarm-design/bem';
import { useMutationObserverRef } from '../utils/hooks';
import { ConfigContext } from '../config-provider';
import { WATERMARK_DEFAULT_STYLES, TEXT_STYLE_DEFAULT, IMAGE_STYLE_DEFAULT, MARK_STYLE_DEFAULT } from './defaults';
import { draw, isContainNode, getUUID, compareUUID, plainStyle } from './utils';
import { noop } from '../utils';
var MUTATION_OBSERVER_CONFIG = {
  childList: true,
  subtree: true,
  attributeFilter: ['class', 'style', 'data-watermark'],
  attributeOldValue: true
};

var WaterMark = function WaterMark(props) {
  var uuid = React.useRef(getUUID());
  var className = props.className,
      text = props.text,
      image = props.image,
      mode = props.mode,
      monitor = props.monitor,
      children = props.children;
  var watermark = React.useRef(null);

  var _React$useState = React.useState(WATERMARK_DEFAULT_STYLES),
      _React$useState2 = _slicedToArray(_React$useState, 2),
      styles = _React$useState2[0],
      setStyels = _React$useState2[1];

  var _React$useContext = React.useContext(ConfigContext),
      prefixCls = _React$useContext.prefixCls;

  var bem = createBEM('water-mark', {
    prefixCls: prefixCls
  });

  var textStyle = _objectSpread(_objectSpread({}, TEXT_STYLE_DEFAULT), props.textStyle);

  var imageStyle = _objectSpread(_objectSpread({}, IMAGE_STYLE_DEFAULT), props.imageStyle);

  var markStyle = _objectSpread(_objectSpread({}, MARK_STYLE_DEFAULT), props.markStyle);

  var rerender = noop;

  var _useMutationObserverR = useMutationObserverRef(function (records, observer) {
    // 重置监听状态
    var reset = function reset(target, cb) {
      if (!target) return;
      observer.disconnect();
      cb === null || cb === void 0 ? void 0 : cb();
      observer.observe(target, MUTATION_OBSERVER_CONFIG);
    };

    records.forEach(function (record) {
      var type = record.type,
          target = record.target,
          attributeName = record.attributeName,
          addedNodes = record.addedNodes,
          removedNodes = record.removedNodes;
      var source = watermark.current;
      if (!source) return; // style 发生变化

      // style 发生变化
      if (type === 'attributes' && target.contains(source)) {
        var _watermark$current;

        attributeName === 'class' && (source === null || source === void 0 ? void 0 : source.removeAttribute('class'));
        attributeName === 'style' && rerender();
        attributeName === 'data-watermark' && reset((_watermark$current = watermark.current) === null || _watermark$current === void 0 ? void 0 : _watermark$current.parentNode, function () {
          return source === null || source === void 0 ? void 0 : source.setAttribute('data-watermark', String(uuid.current));
        });
      } // 篡改节点标签名


      // 篡改节点标签名
      if (type === 'childList' && addedNodes.length) {
        var _element = Array.from(addedNodes).find(function (node) {
          return compareUUID(node, source);
        });

        _element && target.removeChild(_element);
      } // 移除节点


      // 移除节点
      if (type === 'childList' && isContainNode(removedNodes, source)) {
        reset(target, function () {
          ReactDOM.unmountComponentAtNode(source);
          target.appendChild(source);
        });
      }
    });
  }, MUTATION_OBSERVER_CONFIG),
      _useMutationObserverR2 = _slicedToArray(_useMutationObserverR, 2),
      setNode = _useMutationObserverR2[1]; // 渲染水印


  rerender = /*#__PURE__*/function () {
    var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
      var style, _watermark$current2, rest, _yield$draw, url, ratio, width, height;

      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              style = _objectSpread({}, WATERMARK_DEFAULT_STYLES);
              _context.prev = 1;
              rest = {
                text: text,
                image: image,
                textStyle: textStyle,
                imageStyle: imageStyle,
                markStyle: markStyle
              };
              _context.next = 5;
              return draw(rest);

            case 5:
              _yield$draw = _context.sent;
              url = _yield$draw.url;
              ratio = _yield$draw.ratio;
              width = _yield$draw.width;
              height = _yield$draw.height;

              if (url) {
                _context.next = 12;
                break;
              }

              return _context.abrupt("return");

            case 12:
              if (mode === 'repeat') {
                style.backgroundImage = "url(".concat(url, ")");
              } else {
                style.backgroundImage = "url(".concat(url, "), url(").concat(url, ")");
                style.backgroundRepeat = 'repeat, repeat';
                style.backgroundPosition = "".concat(width / 2, "px ").concat(height / 2, "px, 0 0");
              }

              style.backgroundSize = "".concat(width / ratio, "px");
              setStyels(style);
              setNode(monitor ? (_watermark$current2 = watermark.current) === null || _watermark$current2 === void 0 ? void 0 : _watermark$current2.parentElement : null);
              _context.next = 21;
              break;

            case 18:
              _context.prev = 18;
              _context.t0 = _context["catch"](1);
              console.error(_context.t0.message);

            case 21:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, null, [[1, 18]]);
    }));

    return function rerender() {
      return _ref.apply(this, arguments);
    };
  }();

  var isContains = /*#__PURE__*/React.isValidElement(children);
  React.useEffect(function () {
    rerender();
  }, [textStyle.color, textStyle.fontStyle, textStyle.fontWeight, textStyle.fontSize, textStyle.fontFamily, textStyle.fontVariant, textStyle.textAlign, textStyle.textBaseline, imageStyle.width, imageStyle.height, markStyle.width, markStyle.height, markStyle.rotate, markStyle.opacity, markStyle.gapX, markStyle.gapY, markStyle.offsetLeft, markStyle.offsetTop, text, image, mode, monitor, isContains]);
  var style = React.useMemo(function () {
    var properties = _objectSpread(_objectSpread({
      zIndex: markStyle.zIndex
    }, styles), props.style);

    if (isContains) {
      properties.position = 'absolute';
    } // 监视模式写入样式到节点


    if (monitor && watermark.current) {
      var _watermark$current3;

      (_watermark$current3 = watermark.current) === null || _watermark$current3 === void 0 ? void 0 : _watermark$current3.setAttribute('style', plainStyle(properties));
    }

    return properties;
  }, [markStyle.zIndex, monitor, styles, props.style, isContains]);
  var element = /*#__PURE__*/React.createElement("div", {
    ref: watermark,
    "data-watermark": uuid.current,
    style: style
  });
  if (isContains) return /*#__PURE__*/React.createElement("div", {
    className: bem([className])
  }, children, element);
  return element;
};

WaterMark.displayName = 'WaterMark';
WaterMark.defaultProps = {
  textStyle: TEXT_STYLE_DEFAULT,
  imageStyle: IMAGE_STYLE_DEFAULT,
  markStyle: MARK_STYLE_DEFAULT,
  mode: 'interval',
  monitor: true
};
export default WaterMark;