///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
// All rights reserved.
//
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
//
//   This application incorporates Open Design Alliance software pursuant to a
//   license agreement with Open Design Alliance.
//   Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
//   All rights reserved.
//
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////
import { Viewer } from "../Viewer";
import { Point3d } from "./Common/Geometry";
import { OdBaseDragger } from "./Common/OdBaseDragger";

export const MARKUP_ENTITY_TEXT = "$MarkupTempEntity_Text";

export class OdaTextDragger extends OdBaseDragger {
  protected textRef: HTMLTextAreaElement;
  protected m_center: Point3d;
  protected entity: any;
  protected readonly TEXT_HEIGHT_ALIGN = 24;

  constructor(subject: Viewer) {
    super(subject);
    this.press = false;
  }

  override dispose(): void {
    super.dispose();
    this.textRef?.remove();
    this.textRef = null;
  }

  private _finishInput(): void {
    if (this.textRef && this.textRef.value.trimLeft()) {
      this._updateFrame();
    }
    this.textRef?.remove();
    this.textRef = null;
  }

  override start(x: number, y: number, absoluteX: number, absoluteY: number) {
    if (!this.textRef) {
      this.textRef = document.createElement("textarea");
      this.textRef.style.zIndex = "9999";
      this.textRef.style.position = "absolute";
      this.textRef.style.display = "block";
      this.textRef.style.top = absoluteY + "px";
      this.textRef.style.left = absoluteX + "px";
      this.textRef.onkeypress = (event) => {
        if (event.key === "Enter") {
          event.preventDefault();
          this._finishInput();
        }
      };
      document.body.appendChild(this.textRef);

      this.press = true;
      this.m_center = this.screenToWorld(x, y + this.TEXT_HEIGHT_ALIGN);
      this.needInputText = true;
    } else {
      this._finishInput();
    }
  }

  private _updateFrame(): void {
    this.entity = this.getActiveMarkupEntity(MARKUP_ENTITY_TEXT);
    const entityPtr = this.entity.openObject();

    const view = this.getViewer().activeView;
    const pos = this.toPoint(view.viewPosition);
    const target = this.toPoint(view.viewTarget);

    const eyeToWorld = view.eyeToWorldMatrix;
    const eyeDir = pos.sub(target).asVector();

    const xDir = this.toVector([1.0, 0.0, 0.0]);
    const direction = xDir.transformBy(eyeToWorld);

    const mtrx = this.createMatrix3d();
    mtrx.setToWorldToPlane(this.toGeVector(eyeDir));
    direction.transformBy(mtrx);

    const angel = -Math.atan2(-direction.y, direction.x);

    const textSize = 0.02;
    let textScale = 1.0;

    const projMtrx = view.projectionMatrix;
    const mtrxNumber = projMtrx.get(1, 1);
    const tol = 1.0e-6;
    if (!(mtrxNumber < tol && mtrxNumber > -tol)) {
      textScale = 1 / mtrxNumber;
    }

    const geomData = entityPtr.appendText(this.toGePoint(this.m_center), this.textRef.value.trimLeft());
    const textPtr = geomData.openAsText();

    textPtr.setNormal(this.toGeVector(eyeDir));
    textPtr.setRotation(angel);
    textPtr.setTextSize(textSize * textScale);
    textPtr.delete();
    geomData.delete();
    entityPtr.delete();
  }
}
