export interface PointXY {
  a?: number;
  b?: number;
  c?: number;
  d?: number;
  e?: number;
  f?: number;
  g?: number;
  h?: number;
  i?: number;
  j?: number;
  k?: number;
  l?: number;
  m?: number;
  n?: number;
  o?: number;
  p?: number;
  q?: number;
  r?: number;
  s?: number;
  t?: number;
  u?: number;
  v?: number;
  w?: number;
  x: number;
  y: number;
  z?: number;
}
/**
 * Defines 2 limits as numbers
 */

export interface FromToXY {
  from: PointXY;
  to: PointXY;
}

export interface DataXReIm<ArrayType extends NumberArray = NumberArray> {
  /** Array of x values */
  x: ArrayType;

  /** Array of re values */
  re: ArrayType;

  /** Array of im values */
  im: ArrayType;
}
export type NumberArray =
  | number[]
  | Int8Array
  | Uint8Array
  | Uint8ClampedArray
  | Int16Array
  | Uint16Array
  | Int32Array
  | Uint32Array
  | Float32Array
  | Float64Array;
/** Value with units as https://schema.org/Value */
export interface Value {
  /**
   * The value of the quantitative value or property value node.
   * @TJS-examples [0, 1000, 1345.24456, -10, -100]
   */
  value: number;
  /** */
  precision?: number;
  /**A string or text indicating the unit of measurement. The unit could be validated in the input form based on the UN/CEFACT Common Code list */
  units?: string;
}
/**
 * A type that allows one uppercase or lowercase letter
 */
export type OneUpperCase =
  | 'A'
  | 'B'
  | 'C'
  | 'D'
  | 'E'
  | 'F'
  | 'G'
  | 'H'
  | 'I'
  | 'J'
  | 'K'
  | 'L'
  | 'M'
  | 'N'
  | 'O'
  | 'P'
  | 'Q'
  | 'R'
  | 'S'
  | 'T'
  | 'U'
  | 'V'
  | 'W'
  | 'X'
  | 'Y'
  | 'Z';
/**
 * Defines 2 limits as numbers
 */

export interface FromTo {
  from: number;
  to: number;
}
export interface Software {
  /**
   * Version of the software instance.
   * @TJS-examples ['v0.0.1', 'rev111']
   */
  version?: string;
  /**
   *    The name of the item.
   * @TJS-examples ['tga-analysis', 'ChemDraw']
   */
  name: string;
  /**    A description of the item. */
  description?: string;
  /**
   *    If the file can be downloaded, URL to download the binary
   * @TJS-examples ['https://github.com/cheminfo/tga-spectrum/releases/tag/v0.16.0']
   */
  url?: string;
}

/**
 * case we may have a text, ArrayBuffer or Uint8Array
 * This type is used by the package `ensure-string` to ensure that the data
 * is actually a string.
 * This is very useful in the packages like `jcampconverter` or `xy-parser`
 */
export type TextData = string | BinaryData;
/**Describes the location of some object. */
export interface Location {
  /**
   * Name of the institution
   * @TJS-examples ["EPFL", "Heriot-Watt University"]
   */
  entity: string;
  /**
   * Name or code of the building
   * @TJS-examples ["I17", "Main building"]
   */
  building?: string;
  /**Name or code of the room in which the object is localized
   * @TJS-examples ["1 B3", "Lab 1"]
   */
  room?: string;
  /**
   * Internal code that is used to identify the location
   * @TJS-examples ["I17 1 B3"]
   */
  code: string;
}

/**
 * Many libraries use a logger interface to log information about the processing.
 * This logger is expected to be compatible with the one from the `pino` library
 */
export interface Logger extends LightLogger {
  child(bindings?: Record<string, any>): Logger;

  fatal(obj: Record<string, unknown>, message: string): void;
  fatal(message: string): void;
  fatal(error: Error): void;
  fatal(value: unknown, message?: string): void;
}

export type DoubleMatrix = DoubleArray[];
/**
 * A type that allows one uppercase or lowercase letter
 */
export type OneLowerCase =
  | 'a'
  | 'b'
  | 'c'
  | 'd'
  | 'e'
  | 'f'
  | 'g'
  | 'h'
  | 'i'
  | 'j'
  | 'k'
  | 'l'
  | 'm'
  | 'n'
  | 'o'
  | 'p'
  | 'q'
  | 'r'
  | 's'
  | 't'
  | 'u'
  | 'v'
  | 'w'
  | 'x'
  | 'y'
  | 'z';

export interface DataXMatrix<
  DataType extends NumberArray = NumberArray,
  MatrixType extends NumberMatrix = NumberMatrix,
> {
  x: DataType;
  matrix: MatrixType;
}
/**
 * A type that allows one uppercase or lowercase letter
 */
export type OneLetter =
  | 'a'
  | 'b'
  | 'c'
  | 'd'
  | 'e'
  | 'f'
  | 'g'
  | 'h'
  | 'i'
  | 'j'
  | 'k'
  | 'l'
  | 'm'
  | 'n'
  | 'o'
  | 'p'
  | 'q'
  | 'r'
  | 's'
  | 't'
  | 'u'
  | 'v'
  | 'w'
  | 'x'
  | 'y'
  | 'z'
  | 'A'
  | 'B'
  | 'C'
  | 'D'
  | 'E'
  | 'F'
  | 'G'
  | 'H'
  | 'I'
  | 'J'
  | 'K'
  | 'L'
  | 'M'
  | 'N'
  | 'O'
  | 'P'
  | 'Q'
  | 'R'
  | 'S'
  | 'T'
  | 'U'
  | 'V'
  | 'W'
  | 'X'
  | 'Y'
  | 'Z';
export interface OCLMolecule {
  idCode: string;
  coordinates?: string;
  index?: number[]; // should be 16 numbers in fact
}

/**
 * The instrument with which a spectrum was measured.
 *  CHMO: 0000998
 */
export interface Instrument {
  /**
   * The name of the instrument.
   * @TJS-examples ["BELSORP MAX II"]
   */
  model: string;
  /**
   * The name of the instrument manufacturer
   * @TJS-examples ["Microtrac Retsch GmbH", "Bruker"]
   */
  manufacturer: string;
  /**
   * The INTERNAL serial number of the instrument, e.g., the inventory number of the instrument in a university
   * @TJS-examples ["B105863"]
   */
  serialNumber?: string;
  /**
   * Stock Keeping Unit (SKU), i.e. a merchant-specific identifier for a product or service, or the product to which the offer refers.
   * @TJS-examples ["345"]
   */
  sku?: string;
  /**
   * The name of the software and the version number
   * @TJS-examples ["BELMaster™ 7"]
   */
  software?: Software;
  location?: Location;
}
/**
 * Many libraries use a logger interface to log information about the processing.
 * This logger is expected to be compatible not only with the one from the `pino` library but
 * also with the default `console`.
 * This means that the library can output logs by default to the console and the user can
 * replace it with a custom logger that implements this interface.
 */
export interface LightLogger {
  trace(obj: Record<string, unknown>, message: string): void;
  trace(message: string): void;
  trace(error: Error): void;
  trace(value: unknown, message?: string): void;

  debug(obj: Record<string, unknown>, message: string): void;
  debug(message: string): void;
  debug(error: Error): void;
  debug(value: unknown, message?: string): void;

  info(obj: Record<string, unknown>, message: string): void;
  info(message: string): void;
  info(error: Error): void;
  info(value: unknown, message?: string): void;

  warn(obj: Record<string, unknown>, message: string): void;
  warn(message: string): void;
  warn(error: Error): void;
  warn(value: unknown, message?: string): void;

  error(obj: Record<string, unknown>, message: string): void;
  error(message: string): void;
  error(error: Error): void;
  error(value: unknown, message?: string): void;
}
/**
 * In order to store an array of numbers we prefer to either use native javascript
 * arrays or to use Float64Array
 */

export type DoubleArray = number[] | Float64Array;
/**
 *  Quantity that is defined as range, e.g., melting point
 */
export interface Range {
  /** The lower value of some  characteristic or property.*/
  min: number;
  /** The upper value of some characteristic or property.*/
  max: number;
  /** */
  precision?: number;
  /**A string or text indicating the unit of measurement. Useful if you cannot provide a standard unit code for unitCode. */
  units?: string;
}

export type NumberMatrix = NumberArray[];

export interface DataXY<DataType extends NumberArray = NumberArray> {
  /**
   * Array of numbers on x-axis
   */
  x: DataType;
  /**
   * Array of numbers on y-axis
   */
  y: DataType;
}
export type BinaryData = ArrayBuffer | Uint8Array;
export interface PeakXYWidth {
  x: number;
  y: number;
  width: number;
}


export interface MeasurementXY<DataType extends DoubleArray = DoubleArray> {
  /**
   * A unique identifier for the measurement, preferably a UUID.
   */
  id?: string;
  /**
   * Variables containing the data of the measurement.
   * It must contain at least the variable `x` and `y`
   */
  variables: MeasurementXYVariables<DataType>;
  /**
   * Title of the experiment. Often contains the sample code
   */
  title?: string;
  /**
   * May contain the type of data. This is practical when you have a bunch of data
   * of different types
   */
  dataType?: string;
  settings?: {
    instrument?: Instrument;
    [key: string]: any;
  };
  meta?: Record<string, any>;
  derived?: Record<string, any>;
}


export interface MeasurementXYVariables<
  DataType extends DoubleArray = DoubleArray,
> {
  a?: MeasurementVariable<DataType>;
  b?: MeasurementVariable<DataType>;
  c?: MeasurementVariable<DataType>;
  d?: MeasurementVariable<DataType>;
  e?: MeasurementVariable<DataType>;
  f?: MeasurementVariable<DataType>;
  g?: MeasurementVariable<DataType>;
  h?: MeasurementVariable<DataType>;
  i?: MeasurementVariable<DataType>;
  j?: MeasurementVariable<DataType>;
  k?: MeasurementVariable<DataType>;
  l?: MeasurementVariable<DataType>;
  m?: MeasurementVariable<DataType>;
  n?: MeasurementVariable<DataType>;
  o?: MeasurementVariable<DataType>;
  p?: MeasurementVariable<DataType>;
  q?: MeasurementVariable<DataType>;
  r?: MeasurementVariable<DataType>;
  s?: MeasurementVariable<DataType>;
  t?: MeasurementVariable<DataType>;
  u?: MeasurementVariable<DataType>;
  v?: MeasurementVariable<DataType>;
  w?: MeasurementVariable<DataType>;
  x: MeasurementVariable<DataType>;
  y: MeasurementVariable<DataType>;
  z?: MeasurementVariable<DataType>;
}

/**
 * Describe a variable that can only contains as data an array of number
 */
export interface MeasurementVariable<
  DataType extends DoubleArray = DoubleArray,
> {
  /**
   * Unit of the data in the column
   * @TJS-examples ["Pa", "kg"]
   */
  units?: string;
  /**
   * Long name of the column
   *@TJS-examples ["absolute pressure"]
   */
  label: string;
  /**
   *
   */
  isDependent?: boolean;
  /**
   * An array containing numerical data
   */
  data: DataType;
  /** One letter that allows to define the variable */
  symbol?: OneLetter;
  /** If defined contain the minimal value of the data */
  min?: number;
  /** If defined contain the maximal value of the data */
  max?: number;
  /**
   * If defined indicates if the data series is monotonic.
   * `1` means that the data is increasing.
   * `-1` means that the data is decreasing.
   * `0` means that the data is not monotonic.
   */
  isMonotonic?: -1 | 0 | 1;
}
export interface NmrData2DContent {
  z: Float64Array[];
  minZ: number;
  maxZ: number;
  minY: number;
  maxY: number;
  minX: number;
  maxX: number;
}

export type NmrData2D = NmrData2DFid | NmrData2DFt;

export interface NmrData2DFidReIm {
  re: NmrData2DContent;
  im: NmrData2DContent;
}

export interface NmrData2DFid {
  re: NmrData2DContent;
  im?: NmrData2DContent;
}

export interface NmrData2DFt {
  rr: NmrData2DContent;
  ri?: NmrData2DContent;
  ir?: NmrData2DContent;
  ii?: NmrData2DContent;
}
export interface NmrData1D {
  x: Float64Array;
  re: Float64Array;
  im?: Float64Array;
}

/**
 * A single detected particle population with its properties expressed
 * across all available distribution types.
 */
export interface DLSDistribution extends DLSSizeDistribution {
  /** Molecular weight distribution properties. */
  molecularWeight?: DLSDistributionStats;
  /** Diffusion coefficient distribution properties. */
  diffusionCoefficient?: DLSDistributionStats;
  /** Relaxation time distribution properties. */
  relaxationTime?: DLSDistributionStats;
}

/**
 * Statistical properties of a single distribution type for a detected
 * particle population (e.g. the intensity, volume, or number representation
 * of one peak).
 */
export interface DLSDistributionStats {
  /** Mean value in this distribution. */
  mean?: Value;
  /** Area of the peak as a percentage of the total distribution. */
  area?: Value;
  /** Standard deviation of the peak. */
  standardDeviation?: Value;
}

/**
 * Size distribution properties across the three standard weighting types.
 */
export interface DLSSizeDistribution {
  /** Intensity-weighted size distribution properties. */
  intensity?: DLSDistributionStats;
  /** Volume-weighted size distribution properties. */
  volume?: DLSDistributionStats;
  /** Number-weighted size distribution properties. */
  number?: DLSDistributionStats;
}


/**
 * Standardized DLS (Dynamic Light Scattering) metadata.
 * CHMO: 0000120
 */
export interface DLSMeta {
  /** Z-average hydrodynamic diameter (cumulants mean). */
  zAverage?: Value;
  /** Polydispersity index from cumulants analysis. */
  polydispersityIndex?: number;
  /** Derived mean count rate. */
  derivedMeanCountRate?: Value;
  /** Intercept of the correlation function. */
  intercept?: number;
  /** Measured baseline of the correlation function. */
  measuredBaseline?: number;
  /** Fit error of the cumulants analysis. */
  fitError?: number;
  /** First cumulant (mean decay rate). */
  firstCumulant?: number;
  /** Second cumulant (variance of decay rate). */
  secondCumulant?: number;
  /** Overall average properties across all detected particle populations. */
  average?: DLSSizeDistribution;
  /** Detected particle populations, each with properties across all distribution types. */
  distributions?: DLSDistribution[];
}

export interface ICPDilution {
  factor?: number;
  solvent?: string;
}

export interface ICPResult {
  element: string;
  wavelength?: Value;
  experimentalConcentration?: Value;
  dilution?: ICPDilution;
  sampleConcentration?: Value;
}

/**
 * Standardized zeta potential metadata from electrophoretic light scattering
 * (ELS) measurements.
 */
export interface ZetaPotentialMeta {
  /** Mean zeta potential from the distribution. */
  zetaPotential?: Value;
  /** Standard deviation of the zeta potential distribution. */
  zetaDeviation?: Value;
  /** Electrophoretic mobility. */
  mobility?: Value;
  /** Sample conductivity. */
  conductivity?: Value;
  /** Derived mean count rate. */
  derivedMeanCountRate?: Value;
  /** Mean count rate. */
  meanCountRate?: Value;
  /** Quality factor of the measurement. */
  qualityFactor?: number;
}

/** Holder (crucible) used in a TGA experiment. */
export interface TGAHolder {
  /** Type of holder (e.g., "Alumina 70ul"). */
  kind: string;
  /** Mass of the holder. */
  mass: Value;
  /** Material of the holder (e.g., "Ceramic"). */
  material?: string;
}

/**
 * A zone representing a mass-loss step in a TGA experiment.
 * Zones are typically extracted from instrument software output
 * (e.g., Mettler Toledo "Results" section).
 */
export interface TGAZone {
  /** Relative mass loss as a fraction (0 to 1). */
  relativeMassLoss: number;
  /** Absolute mass loss with units. */
  massLoss: Value;
  /** Start of the temperature range for this zone. */
  from?: Value;
  /** End of the temperature range for this zone. */
  to?: Value;
  /** Type of the zone (e.g., "horizontal", "Residual"). */
  kind: string;
  /** Temperature at the inflection point of the mass-loss curve. */
  inflectionPoint?: Value;
  /** Temperature at the midpoint of the mass-loss step. */
  middlePoint?: Value;
}


/**
 * Standardized TGA metadata.
 * CHMO: 0000690
 */
export interface TGAMeta {
  /** Measurement method name (e.g., "650 TGA/DSC", "Full"). */
  method?: string;
  /** Mass-loss zones extracted from the instrument software. */
  zones?: TGAZone[];
  /** Holder (crucible) information. */
  holder?: TGAHolder;
  /** Initial sample mass before the experiment. */
  initialValue?: Value;
  /** Sample mass. */
  sampleMass?: Value;
}
