// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { DataAttributes } from "./circuit.js";
import { Register } from "./register.js";

/**
 * Enum for the various gate operations handled.
 */
export enum GateType {
  /** Measurement gate. */
  Measure,
  /** CNOT gate. */
  Cnot,
  /** SWAP gate. */
  Swap,
  /** X gate. */
  X,
  /** |0⟩or |1⟩ gate. */
  Ket,
  /** Single/multi qubit unitary gate. */
  Unitary,
  /** Single/multi controlled unitary gate. */
  ControlledUnitary,
  /** Group of nested gates */
  Group,
  /** Invalid gate. */
  Invalid,
}

/**
 * Rendering data used to store information pertaining to a given
 * operation for rendering its corresponding SVG.
 */
export interface GateRenderData {
  /** Gate type. */
  type: GateType;
  /** Whether this group gate is currently expanded. Always false for non-group gates. */
  isExpanded: boolean;
  /** Centre x coord for gate position. */
  x: number;
  /** Array of y coords of control registers. */
  controlsY: number[];
  /** Array of y coords of target registers.
   *  For `GateType.Unitary` or `GateType.ControlledUnitary`, this is an array of groups of
   *  y coords, where each group represents a unitary box to be rendered separately.
   */
  targetsY: (number | number[])[];
  /** Gate label. */
  label: string;
  /** Gate arguments as string. */
  displayArgs?: string;
  /** Gate width. */
  width: number;
  /** Children operations as part of group. */
  children?: GateRenderData[][];
  /** Vertical space from the top of this gate to the top of the topmost contained gate. 0 for non-groups. */
  topPadding: number;
  /** Vertical space from the bottom of this gate to the bottom of the bottommost contained gate. 0 for non-groups. */
  bottomPadding: number;
  /** Custom data attributes to attach to gate element. */
  dataAttributes?: DataAttributes;
  /** Link href and title for clickable gate. */
  link?: { href: string; title: string };
  /** Labels for the classical control registers (when present, this group is rendered with classical controls). */
  classicalControlIds?: (number | null)[];
  /**
   * Classical control registers used by this operation or any descendant.
   * Used by processOperations to decide which classical wires may pass through
   * this gate body without forcing a split.
   */
  classicalControlRegs?: Register[];
}
