var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MapToComponentField, MapToComponentMethod, VegaSlimmer } from 'vega-slimmer/core';
import { FORM_ELEMENT_VALUE_CHANGE } from '../../../../../helpers/change-manager/subject/static-subject/static-subject-title';
import ChangeManager from '../../../../../helpers/change-manager/change-manager';
import { deepEqual } from '../../../../../utils/object';
import { emptySanitizeStrategy, htmlSanitizer } from '../../../../../utils/sanitize';
/**
 * Signature written mode controller
 */
export class WrittenModeSvgController extends VegaSlimmer {
  constructor() {
    super(...arguments);
    this.penWidth = '4px';
    /**
     * Clear the signature
     */
    this.clear = () => {
      this.signatureContainerRef.innerHTML = htmlSanitizer.sanitize('', emptySanitizeStrategy);
      this.value = null;
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-signature-capture-on-draw-signature}
     */
    /* istanbul ignore next */
    /**
     * Start drawing the current path
     *
     * @param {MouseEvent} e - MouseEvent
     */
    this.startDrawing = (e) => {
      if (this.disabled)
        return;
      this.isDrawing = true;
      const { x, y } = this.getPoint(e);
      // eslint-disable-next-line no-restricted-globals
      this.currentPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      this.currentPath.setAttribute('d', `M ${x} ${y}`);
      this.currentPath.setAttribute('stroke', 'rgba(4, 4, 28, 1)');
      this.currentPath.setAttribute('stroke-width', this.penWidth);
      this.currentPath.setAttribute('fill', 'none');
      this.currentPath.setAttribute('stroke-linecap', 'round');
      this.currentPath.setAttribute('stroke-linejoin', 'round');
      this.signatureContainerRef.appendChild(this.currentPath);
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-signature-capture-on-draw-signature}
     */
    /* istanbul ignore next */
    /**
     * Get the current mouse position.
     * In cypress case, when the mousedown event signature is triggered, the event type is 'Event', which adds compatibility
     *
     * @param {MouseEvent | TouchEvent} e - MouseEvent on desktop or TouchEvent on mobile
     * @returns {VegaSignatureMousePosition} - Current mouse position
     */
    this.getPoint = (e) => {
      var _a, _b;
      const rect = this.signatureContainerRef.getBoundingClientRect();
      const clientX = (_a = e['clientX']) !== null && _a !== void 0 ? _a : e['touches'][0].clientX;
      const clientY = (_b = e['clientY']) !== null && _b !== void 0 ? _b : e['touches'][0].clientY;
      return {
        x: clientX - rect.left,
        y: clientY - rect.top,
      };
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-signature-capture-on-draw-signature}
     */
    /* istanbul ignore next */
    /**
     * Draw the current path to the end point
     *
     * @param {MouseEvent} e - Mouse event
     */
    this.draw = (e) => {
      if (!this.isDrawing)
        return;
      const { x, y } = this.getPoint(e);
      const d = this.currentPath.getAttribute('d');
      this.currentPath.setAttribute('d', `${d} L ${x} ${y}`);
    };
    /*
     * The below method is e2e-test covered in
     * @see{module:vega-signature-capture-on-draw-signature}
     */
    /* istanbul ignore next */
    /**
     * Stop drawing and update the value
     */
    this.stopDrawing = () => {
      if (!this.isDrawing)
        return;
      this.isDrawing = false;
      this.value = { type: 'written', img: this.generateSignatureImage() };
    };
  }
  /**
   * Setup written listeners
   */
  componentDidLoad() {
    this.setupListeners();
    this.fillSignature(this.value);
  }
  /**
   * Clear the signature
   */
  handleClear() {
    this.clear();
  }
  /**
   * Emit the vegaChange event when value changed
   *
   * @param {VegaSignatureValue} newValue - The `newValue` parameter is a object representing the new value for the signature capture.
   * @param {VegaSignatureValue} oldValue - The `oldValue` parameter is a object representing the old value for the signature capture.
   */
  watchValue(newValue, oldValue) {
    if (deepEqual(newValue, oldValue))
      return;
    this.changeEventEmitter.emit(newValue);
    this.fillSignature(newValue);
    ChangeManager.notify(FORM_ELEMENT_VALUE_CHANGE, {
      host: this.host,
      detail: newValue,
    });
  }
  /**
   * Set the signature container ref
   *
   * @param {SVGElement} ref - signature container ref
   */
  setSignatureContainerRef(ref) {
    this.signatureContainerRef = ref;
  }
  /**
   * Setup the listeners, for desktop and mobile
   */
  setupListeners() {
    const container = this.signatureContainerRef;
    container.addEventListener('mousedown', this.startDrawing);
    container.addEventListener('mousemove', this.draw);
    container.addEventListener('mouseup', this.stopDrawing);
    container.addEventListener('mouseleave', this.stopDrawing);
    // For mobile
    container.addEventListener('touchstart', this.startDrawing);
    container.addEventListener('touchmove', this.draw);
    container.addEventListener('touchend', this.stopDrawing);
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-signature-capture-on-draw-signature}
   */
  /* istanbul ignore next */
  /**
   * Generate the signature base64 image string
   *
   * @returns {string} - base64 image string
   */
  generateSignatureImage() {
    const serializer = new XMLSerializer();
    // TODO: Adding the SVG attribute will cause changes to the generated base64 value, leading to problems. https://gethired.atlassian.net/browse/VD-7854
    const svgData = serializer.serializeToString(this.signatureContainerRef);
    const base64Svg = btoa(unescape(encodeURIComponent(svgData)));
    return `data:image/svg+xml;base64,${base64Svg}`;
  }
  /**
   * Parse the value to svg
   *
   * @param {VegaSignatureValue} value - Signature value
   * @returns {Nullable<HTMLElement>} - SVG element
   */
  fromDataURL(value) {
    if (!value || !value.img)
      return;
    const base64Svg = this.value.img.replace('data:image/svg+xml;base64,', '');
    return new DOMParser().parseFromString(atob(base64Svg), 'image/svg+xml').documentElement;
  }
  /**
   * Fill the signature from the value.
   * Not fill the signature if the signature container already has child nodes, that means in written status.
   *
   * @param {VegaSignatureValue} value - Signature value
   */
  fillSignature(value) {
    this.signatureContainerRef.replaceChildren();
    const signature = this.fromDataURL(value);
    if (signature) {
      const paths = Array.from(signature.childNodes);
      this.signatureContainerRef.append(...paths);
    }
  }
}
__decorate([
  MapToComponentField()
], WrittenModeSvgController.prototype, "changeEventEmitter", void 0);
__decorate([
  MapToComponentField()
], WrittenModeSvgController.prototype, "host", void 0);
__decorate([
  MapToComponentField({ writable: true })
], WrittenModeSvgController.prototype, "value", void 0);
__decorate([
  MapToComponentField({ writable: true })
], WrittenModeSvgController.prototype, "isDrawing", void 0);
__decorate([
  MapToComponentField()
], WrittenModeSvgController.prototype, "disabled", void 0);
__decorate([
  MapToComponentMethod('componentDidLoad')
], WrittenModeSvgController.prototype, "componentDidLoad", null);
__decorate([
  MapToComponentMethod('clear')
], WrittenModeSvgController.prototype, "handleClear", null);
__decorate([
  MapToComponentMethod('watchValue')
], WrittenModeSvgController.prototype, "watchValue", null);
