import {ShapeControls} from "@client/canvas/containers/elements/shape-controls.mjs";

/**
 * @import DrawingDocument from "@client/documents/drawing.mjs";
 * @import Drawing from "@client/canvas/placeables/drawing.mjs";
 * @import DrawingsLayer from "@client/canvas/layers/drawings.mjs";
 * @import {RectangleShapeData, EllipseShapeData, PolygonShapeData} from "@common/data/_module.mjs";
 */

/**
 * Controls for a Drawing shape.
 * @extends {ShapeControls<DrawingDocument, Drawing, DrawingsLayer,
 *   RectangleShapeData|EllipseShapeData|PolygonShapeData>}
 */
export default class DrawingShapeControls extends ShapeControls {

  /** @override */
  _drawShape(graphics) {
    if ( this.shape.type !== "polygon" ) {
      this.shape.drawShape(graphics);
      return;
    }
    const isClosed = this.document.fillType || (this.shape.points.slice(0, 2).equals(this.shape.points.slice(-2)));
    if ( isClosed ) graphics.drawPolygon(this.shape.points);
    else graphics.drawPath(this.shape.points);
  }

  /* -------------------------------------------- */

  /** @inheritDoc */
  _onDragStart(event) {
    super._onDragStart(event);

    // Handle transformation of other controlled drawings
    if ( event.interactionData.handle.name === "translate" ) {
      const others = event.interactionData.others = [];
      for ( const object of this.layer.controlled ) {
        if ( object !== this.object ) others.push(ShapeControls._createDragPreview(object));
      }
    }
  }

  /* -------------------------------------------- */

  /** @inheritDoc */
  _onDragMove(event) {
    const {handle, destination, shape, preview} = event.interactionData;
    if ( (shape.type !== "polygon") || (handle.name !== "rotate") ) return super._onDragMove(event);
    const snap = !event.shiftKey;
    canvas._onDragCanvasPan(event);
    const {x: x0, y: y0} = this.shape.origin;
    const [x1, y1] = this.shape.points;
    let rotation = this.document.rotation + (Math.toDegrees(Math.atan2(destination.y - y0, destination.x - x0))
      - Math.toDegrees(Math.atan2(y1 - y0, x1 - x0)));
    if ( snap ) rotation = shape._getSnappedRotation(rotation);
    else rotation = Math.round(rotation);
    preview.document.updateSource({rotation});
    preview.renderFlags.set({refreshRotation: true});
  }

  /* -------------------------------------------- */

  /** @override */
  _updateDragPreview(event) {
    this.layer._updateDragPreview(event);

    // Handle translation of other controlled drawings
    if ( !event.interactionData.others?.length ) return;
    const {preview} = event.interactionData;
    const dx = preview.document.x - this.document.x;
    const dy = preview.document.y - this.document.y;
    for ( const preview of event.interactionData.others ) {
      const {x, y} = preview._original.document._source;
      preview.document.updateSource({x: x + dx, y: y + dy});
      preview.renderFlags.set({refreshPosition: true});
    }
  }

  /* -------------------------------------------- */

  /** @override */
  _prepareDragDropUpdate(event) {
    const {x, y, shape: {width, height, points}, rotation} = event.interactionData.preview.document._source;
    return {x, y, shape: {width, height, points}, rotation};
  }

  /* -------------------------------------------- */

  /** @inheritDoc */
  _onDragDrop(event) {

    // Handle translation of multiple controlled drawings
    if ( event.interactionData.others?.length ) {
      event.interactionData.clearPreviewContainer = false;
      const {x, y} = event.interactionData.preview.document._source;
      const updates = [{_id: this.document.id, x, y}];
      for ( const preview of event.interactionData.others ) {
        const {x, y} = preview.document._source;
        updates.push({_id: preview._original.document.id, x, y});
      }
      this.document.parent.updateEmbeddedDocuments("Drawing", updates).finally(() => {
        this.layer.clearPreviewContainer();
      });
      return;
    }

    return super._onDragDrop(event);
  }

  /* -------------------------------------------- */

  /** @override */
  _onClick2(event) {
    this.document.sheet.render({force: true});
  }
}
