import * as THREE from "three";
import type { ErrorMessageKey } from "./i18n";

export type TMovementSensor = "I" | "U" | "D" | "?" | "";

export type TDoorPositions = "" | "?" | "C" | "O" | "-" | "+" | "X";

export interface ILiftStatusRow {
  date_value: string;
  duration?: number;
  next_ts?: Date;
  next_val: string;
  pos: number;
  prev_duration?: number;
  prev_ts?: Date;
  prev_val: string;
  ts: Date;
  val: string;
  start?: number;
  end?: number;
  from_ts?: string;
  to_ts?: string;
}

export interface ILiftStatusSensor {
  id: string;
  type: string;
  name: string;
  internal: string;
  high_volume: string;
}

export interface ILiftStatusSensorResponse {
  rows: ILiftStatusRow[];
  sensor: ILiftStatusSensor;
}

export interface ILiftStatusAuth {
  tokenData: ITokenData;
  response: IAuthResponse;
  type: string;
}

export interface ITokenData {
  org: string;
  oid: string;
  otype: string;
  cmds: boolean;
  iat: number;
  exp: number;
  aud: string;
  iss: string;
  sub: string;
}

export interface IAuthResponse {
  es_number: string;
  capability: IAuthResponseCapability;
  permissions: IAuthResponsePermissions;
}

export interface IAuthResponseCapability {
  lift_controller: ILiftController;
}

export interface ILiftController {
  type: string;
}

export interface IAuthResponsePermissions {
  lift_flow: ILiftFlow;
  commands: boolean;
}

export interface ILiftFlow {
  data: ILiftFlowData;
}

export interface ILiftFlowData {
  realtime: boolean;
  statuses: boolean;
  counters: boolean;
  history: boolean;
}

export interface ILiftStatusValues {
  /** Sense module verbonden met SenseCloud, de verbinding tussen de Sense Module en SenseCloud. (1 is verbonden) */
  10?: number;

  /** Mobiele signaalsterkte, waarde in procenten */
  23?: number;

  /** SenseCloud Round Trip Time - afgelopen uur (in ms) */
  25?: number;

  /** SenseCloud Round Trip Time - afgelopen 24 uur (in ms) */
  26?: number;

  /** Sturing verbinding met Sense module gezond (1 indien gezond) */
  50?: boolean;

  /** Rittenteller */
  100?: number;

  /** Installatie onbeschikbaar (1 indien onbeschikbaar) */
  103?: boolean;

  /** Bezoek */
  104?: boolean;

  /** Onbeschikbaar */
  105?: boolean;

  /** Onbeschikbaar buiten bezoek */
  106?: boolean;

  /** Noodstop verzamel */
  107?: boolean;

  /** Voeding installatie */
  108?: boolean;

  /** Energieverbruik teller */
  109?: number;

  /** Status reset contact */
  110?: boolean;

  /** Storingscontact */
  201?: boolean;

  /** Data storingsverzamelsensor met beschikbaarheidsimpact */
  210?: boolean;

  /** Data storingsverzamelsensor zonder beschikbaarheidsimpact */
  211?: boolean;

  /** Bewegingstoestand */
  500?: TMovementSensor;

  /** Huidige stopplaats (geopende deuren) */
  501?: number;

  /** Deur positie (status) - voor */
  502?: TDoorPositions;

  /** Deur positie (status) - achter */
  503?: TDoorPositions;

  /** Deurlijn */
  505?: boolean;

  /** Temperatuurregelaar (-100 t/m 200) */
  506?: number;

  /** Richtingveranderingenteller */
  507?: number;

  /** Deurcyclus teller - deur voor */
  508?: number;

  /** Deurcyclus teller - deur achter */
  509?: number;

  /** Deurcyclus teller per stopplaats - deur voor */
  510?: string; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Deurcyclus teller per stopplaats - deur achter */
  511?: string; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Stopplaatsteller */
  512?: string; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Statuscodes
   * Comma separated list of:
   * identifier:timestamp:status
   *
   * Where the identifier is the status code identifier,
   * timestamp is Unix timestamp in milliseconds and
   * status is 1 or 0 based on the status being active or not.
   */
  513?: string;

  /** Laatst gepasseerde stopplaats */
  514?: number;

  /** Huidige stopplaats */
  515?: number | string;

  /** Deurbeweging teller - deur voor */
  516?: number;

  /** Deurbeweging teller - deur achter */
  517?: number;

  /** Deurbeweging teller per stopplaats - deur voor */
  518?: string; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Deurbeweging teller per stopplaats - deur achter */
  519?: string; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Deur pendeling teller - deur voor */
  520?: number;

  /** Deur pendeling teller - deur achter */
  521?: number;

  /** Deur pendeling teller per stopplaats - deur voor */
  522?: string; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Deur pendeling teller per stopplaats - deur voor */
  523?: number; // TODO: this is a counter LIST, figure out what this sensor returns. we can prob do better than string

  /** Sturing verbonden met Sense module (1 indien verbonden) */
  524?: number;

  /** Na oproep geen reactie (Carcall request no response) */
  550?: boolean;

  /** Sturing informatie */
  590?: string;
}

export type SensorId = keyof ILiftStatusValues;

export interface ILiftStatusUpdated {
  /** Sense module verbonden met SenseCloud, de verbinding tussen de Sense Module en SenseCloud. (1 is verbonden) */
  10?: number;

  /** Mobiele signaalsterkte, waarde in procenten */
  23?: number;

  /** SenseCloud Round Trip Time - afgelopen uur (in ms) */
  25?: number;

  /** SenseCloud Round Trip Time - afgelopen 24 uur (in ms) */
  26?: number;

  /** Sturing verbinding met Sense module gezond (1 indien gezond) */
  50?: number;

  /** Rittenteller */
  100?: number;

  /** Installatie onbeschikbaar (1 indien onbeschikbaar) */
  103?: number;

  /** Bezoek */
  104?: number;

  /** Onbeschikbaar */
  105?: number;

  /** Onbeschikbaar buiten bezoek */
  106?: number;

  /** Noodstop verzamel */
  107?: number;

  /** Voeding installatie */
  108?: number;

  /** Energieverbruik teller */
  109?: number;

  /** Status reset contact */
  110?: number;

  /** Storingscontact */
  201?: number;

  /** Data storingsverzamelsensor met beschikbaarheidsimpact */
  210?: number;

  /** Data storingsverzamelsensor zonder beschikbaarheidsimpact */
  211?: number;

  /** Bewegingstoestand */
  500?: number;

  /** Huidige stopplaats (geopende deuren) */
  501?: number;

  /** Deur positie (status) - voor */
  502?: number;

  /** Deur positie (status) - achter */
  503?: number;

  /** Deurlijn */
  505?: number;

  /** Temperatuurregelaar (-100 t/m 200) */
  506?: number;

  /** Richtingveranderingenteller */
  507?: number;

  /** Deurcyclus teller - deur voor */
  508?: number;

  /** Deurcyclus teller - deur achter */
  509?: number;

  /** Deurcyclus teller per stopplaats - deur voor */
  510?: number;

  /** Deurcyclus teller per stopplaats - deur achter */
  511?: number;

  /** Stopplaatsteller */
  512?: number;

  /** Statuscodes
   * Comma separated list of:
   * identifier:timestamp:status
   *
   * Where the identifier is the status code identifier,
   * timestamp is Unix timestamp in milliseconds and
   * status is 1 or 0 based on the status being active or not.
   */
  513?: number;

  /** Laatst gepasseerde stopplaats */
  514?: number;

  /** Huidige stopplaats */
  515?: number;

  /** Deurbeweging teller - deur voor */
  516?: number;

  /** Deurbeweging teller - deur achter */
  517?: number;

  /** Deurbeweging teller per stopplaats - deur voor */
  518?: number;

  /** Deurbeweging teller per stopplaats - deur achter */
  519?: number;

  /** Deur pendeling teller - deur voor */
  520?: number;

  /** Deur pendeling teller - deur achter */
  521?: number;

  /** Deur pendeling teller per stopplaats - deur voor */
  522?: number;

  /** Deur pendeling teller per stopplaats - deur voor */
  523?: number;

  /** Verbinding met sturing gezond (1 indien gezond) */
  524?: number;

  /** Na oproep geen reactie (Carcall request no response) */
  550?: number;

  /** Sturing informatie */
  590?: number;
}

export interface ILiftStatusSensorDataResponse {
  lastUpdate: number;
  values: ILiftStatusValues;
  updated: ILiftStatusUpdated;
}

export interface ILiftStatusMessage {
  mid: string;
  f: string;
  data: ILiftStatusValues;
  ts: number;
  mc: number;
  rts: number;
}

export interface ILiftStatusModuleStatus {
  es: string;
  message: ILiftStatusMessage;
}

export interface IElevatorMaterials {
  active: THREE.MeshStandardMaterial;
  normal: THREE.MeshStandardMaterial;
  pulseOn: THREE.MeshStandardMaterial;
  pulseOff: THREE.MeshStandardMaterial;
  transparent: THREE.MeshStandardMaterial;
  floor: THREE.MeshStandardMaterial;
  door: THREE.MeshStandardMaterial;
}

export interface ITimePoint {
  x: Date;
  y: number;
  id: string;
  // TODO: this should be a sensor ID, but for now we use number. Create an enum for sensor IDs
  sensor: number;
  fake: boolean;
}

export type TLiftStatusWebComponentErrorType =
  | ""
  | "Socket"
  | "API"
  | "Token"
  | "Controller"
  | "Sensecloud";

export interface ILiftStatusWebComponentError {
  hasError: boolean;
  messageKey: ErrorMessageKey | undefined;
  type: TLiftStatusWebComponentErrorType;
}

// Changes to this type need to be reflected in isSeverity function
export type TSeverity = "" | "impact" | "informational" | "non-impact";

export interface IStatusMessage {
  id: string;
  humanReadableTimestamp: string;
  relativeTimestamp: string;
  description: string;
  severity: TSeverity;
}

export interface IStatusCode {
  description: string;
  level: TSeverity;
}

/**
 * The ID type in the object ID claim. Can be internal, installation or external. Derived from the token.
 */
export type TObjectType = "internal" | "installation" | "external";

export interface DatePicker {
  /**
   * The start date/time in ISO 8601 format
   */
  start: string;
  /**
   * The end date/time in ISO 8601 format
   */
  end: string;
}
