/*
export interface Meta {
  totalCount: number;
}

export interface CtrlAttrs {
  [key: string]: CtrlAttr;
}

export interface CtrlAttr {
  name: string;
  cmd: string;
  cmdClass: string;
  icon: string;
  cnfrm: boolean;
  delay: number;
}

export interface DevCtrlAttr {
  name: string;
  cmd: DeviceCommands;
  cmdClass: 'device_control';
  icon: string;
  cnfrm: boolean;
  delay: number;
}
*/

export type FavoriteCommands = 'set' | 'delete' | 'get';

export type SimulationCommands =
  'restart'
  | 'start'
  | 'pause'
  | 'resume'
  | 'reset'
  | 'clear'
  | 'end'
  | 'add'
  | 'test-mode'
  | 'delete'
  | 'next'
  | 'gps-noise';

export type DeviceCommands = 'shutdown' | 'reboot';

export type TunneldCommands =
  | 'start'
  | 'start-watcher'
  | 'end-watcher'
  | 'shutdown'
  | 'restart'
  | 'clear'
  | 'cancel';

export interface LocationQueue {
  [key: string]: LocationMark;
}

export interface LocationMarkUpdateResponse {
  command_status: string;
  command: string;
  command_class: string;
  message: string;
  data: LocationMark;
}

export interface QueueOrderUpdateResponse {
  command_status: string;
  command: string;
  command_class: string;
  message: string;
  data: string[];
}

export interface LocationMark {
  loc_id: string;
  latitude: number | undefined | null;
  longitude: number | undefined | null;
  address?: string | undefined | null;
  delay?: number | undefined | null;
  start: string | undefined | null;
  status: string | undefined | null;
  end?: string | undefined | null;
}

// SERVER TO CLIENT

export interface ServerToClientEvents {
  // built-in
  noArg: () => void;
  withAck: (a: string, callback: (b: number) => void) => void;
  message: (e: string) => void;
  error: (data: ErrorFull) => void;
  // testing
  test_prompt: (callback: (s: string) => void) => void;
  // deprecated
  simulation_status: (c: SimulationStatus) => void;
  // future
  device_status: (d: DeviceStatus) => void;
  // in-use
  status: (d: StatusUpdate) => void;
  app_error: (data: AppError) => void;
  icloud_2fa_request: (callback: (e: number) => void) => void;
  fmf_update: (d: FindMyUpdate) => void;
  queue_data_update: (d: QueueData) => void;
  location_item_update: (d: LocationItemUpdate) => void;
}

export interface AppError {
  type: string;
  message: string;
  error: string;
  data: {
    udids?: string | null | undefined;
    udid?: string | null | undefined;
    disconnected_udids?: string | null | undefined;
    tunnel_timeout_seconds?: string | null | undefined;
    dvt_timeout_seconds?: string | null | undefined;
  };
}

export interface LocationItemUpdate {
  loc_id: string;
  data: LocationMark;
}

export interface SimulationStatus {
  loc_id: string;
  latitude: number;
  longitude: number;
}

export interface icloudData {
  consumer_queue: string | number | boolean;
  consumer_task: string | boolean;
  monitor_enabled: boolean;
  monitor_task: string | boolean;
  monitor_running: boolean;
}

export interface QueueData {
    active: boolean;
    data: LocationQueue;
    order: string[];
    deleted_items: string[];
    state: string | undefined | null;
    worker_task: string | undefined | null;
    gps_noise: boolean;
    test_mode: boolean;
}

export interface StatusUpdate {
  connected_clients: { [key: string]: string };
  current_location: {
    loc_id: string;
    latitude: number | undefined | null;
    longitude: number | undefined | null;
    start?: string | undefined | null;
  };
  device_name: string | undefined | null;
  fmf_location: FindMyUpdate | undefined | null;
  icloud: icloudData;
  next_move?: number | undefined | null;
  set_location_enabled: boolean;
  simulation_queue: QueueData
  tunnel: string | undefined | null;
  tunnel_watcher_running: boolean;
  device_count?: number | undefined | null;
  udid?: string | null;
  product_version?: string | null | undefined;
  phone_number?: string | null | undefined;
  developer_mode_enabled?: boolean | undefined | null;
  ddi_mounted?: boolean;
  rsd_address?: string | null | undefined;
  rsd_port?: number | undefined | null;
  lockdown_trusted_port?: number | undefined | null;
  lockdown_untrusted_port?: number | undefined | null;
  lockdown_trusted_reachable?: boolean | undefined | null;
  lockdown_untrusted_reachable?: boolean | undefined | null;
  dtservicehub_reachable?: boolean | undefined | null;
}

interface DeviceStatus {
  device_connected: boolean;
  device_count: number;
  udid?: string | null;
  device_name?: string | null;
  product_version?: string | null;
  phone_number?: string | null;
  developer_mode_enabled?: boolean;
  ddi_mounted?: boolean;
  rsd_address?: string | null;
  rsd_port?: number;
  lockdown_trusted_port?: number;
  lockdown_untrusted_port?: number;
  lockdown_trusted_reachable?: boolean;
  lockdown_untrusted_reachable?: boolean;
  dtservicehub_reachable?: boolean;
}

export interface ErrorFull {
  type: string;
  error: string;
}

export interface FindMyUpdate {
  altitude: number;
  batteryLevel: number;
  deviceDisplayName: string;
  deviceStatus: number;
  horizontalAccuracy: number;
  latitude: number;
  longitude: number;
  name: string;
  timeStamp: number;
  verticalAccuracy: number;
}

// END SERVER TO CLIENT

// CLIENT TO SERVER

export interface ClientToServerEvents {
  // built-in
  message: (e: string, callback: (b: boolean, r: string) => void) => void;
  // testing
  send_test_prompt: (p: string, callback: (response: string) => void) => void;
  // status
  request_update: (callback: (response: StatusUpdate) => void) => void;
  // control
  tunneld_control: (
    args: {
      command: TunneldCommands;
      udid?: string;
    },
    callback?: (response: TunneldControlResponse) => void,
  ) => void;
  favorite_control: (
    args: {
      command: FavoriteCommands;
      favorite?: Favorite | undefined | null;
    },
    callback: (response: FavoriteControlResponse) => void,
    ) => void;
  simulation_control: (
    args: {
      command: SimulationCommands;
      latitude?: number | null | undefined;
      longitude?: number | null | undefined;
      delay?: number | null | undefined;
      loc_id?: string | null | undefined;
      address?: NominatimResponse | string | null | undefined;
    },
    callback: (response: SimulationControlResponse) => void,
  ) => void;
  device_control: (
    args: {
      command: DeviceCommands;
      delay?: number;
    },
    callback?: (response: DeviceControlResponse) => void,
  ) => void;
  icloud_monitor_control: (
    args: {
      command: string;
    },
    callback?: (response: iCloudMonitorResponse) => void,
  ) => void;
  // data updates
  location_item_update: (
    args: {
      loc_id: string;
      key: string;
      value: string | number;
    },
    callback?: (response: LocationMarkUpdateResponse) => void,
  ) => void;
  queue_order_update: (
    args: {
      newOrder: string[];
    },
    callback?: (response: QueueOrderUpdateResponse) => void,
  ) => void;
  // data requests
  reverse_geocode: (
    args: {
      latitude: number;
      longitude: number;
    },
    callback?: (response: GeoCacheResponse) => void,
  ) => void;
}

export interface FavoriteControlResponse {
  command_status: string;
  command: FavoriteCommands;
  command_class: string;
  data?: {
    favorites: Favorite[] | undefined | null;
  };
  message?: string | undefined;
}

export interface SimulationControlResponse {
  command_status: string;
  command: SimulationCommands;
  command_class: string;
  data?: SimulationControlResponseData | undefined | null;
  message?: string | undefined;
}

interface SimulationControlResponseData {
  simulation_queue?: QueueData;
  location_item?: LocationMark;
}

interface DeviceControlResponse {
  command_status: string;
  command_class: string;
  command: DeviceCommands;
  message?: string;
}


interface TunneldControlResponse {
  command_status: string;
  command_class: string;
  command: TunneldCommands;
  message?: string;
}

export interface iCloudMonitorResponse {
  command_status: string;
  command: string;
  command_class: string;
  icloud_monitor_enabled?: boolean | undefined | null;
  icloud_monitor_running?: boolean | undefined | null;
  message?: string | undefined | null;
  error?: string | undefined | null;
}

// END CLIENT TO SERVER

export interface coords {
  lat: number;
  lng: number;
}

import type { OpenStreetMapProvider } from 'leaflet-geosearch';
export interface SearchControlProps {
  provider: OpenStreetMapProvider;
  showMarker: boolean;
  autoClose: boolean;
  updateMap: boolean;
  showPopup: boolean;
  style: 'button' | 'bar';
  acceptAutoLoad: boolean;
  autoComplete: boolean;
  autoCompleteDelay: number;
  retainZoomLevel: boolean;
  animateZoom: boolean;
  keepResult: boolean;
}

export interface CurrentLocation {
  loc_id: string;
  latitude: number | null | undefined;
  longitude: number | null | undefined;
  //  start_time?: string | null | undefined;
  //  end_time?: string | null | undefined
  next_move?: number | null | undefined;
}

export interface NextLocation {
  loc_id: string;
  latitude: number;
  longitude: number;
  time_at_location?: number | null;
}

/*
export interface NominatimReverseResponse {
  place_id: number;
  licence: string;
  osm_type: string;
  osm_id: number;
  lat: string;
  lon: string;
  class: string;
  type: string;
  place_rank: number;
  importance: number;
  addresstype: string;
  name: string;
  display_name: string;
  address: NominatimAddress;
  boundingbox: string[];
}

export interface NominatimAddress {
  house_number: string;
  road: string;
  village?: string;
  city?: string;
  county: string;
  state: string;
  'ISO3166-2-lvl4': string;
  postcode: string;
  country: string;
  country_code: string;
}
*/

export interface routeSegments {
  fromWaypoint: number;
  toWaypoint: number;
  distanceMeters: number;
  timeSeconds: number;
  toCoordinates: LatLng;
}

export interface RoutesSet {
  [key: string]: RouteSet;
}

export interface LatLng {
  lat: number | null | undefined;
  lng: number | null | undefined;
}

export interface routeDirections {
  dirIndex?: number | undefined;
  coordinateIndex: number;
  text?: string | undefined;
  distance?: number | undefined;
  time?: number | undefined;
  coordinates: LatLng | null | undefined;
}

export interface routeCoordinates {
  coordinateIndex: number;
  lat: number;
  lng: number;
  distanceFromPrev: number;
  timeFromPrev: number;
  instruction: string;
}

export interface RouteSet {
  start: [number, number] | [null, null] | [undefined, undefined] | null | undefined;
  end: [number, number] | [null, null] | [undefined, undefined] | null | undefined;
  wayPoints?: [number, number][] | [null, null] | [undefined, undefined] | null | undefined;
}

export interface Favorite {
  name: string | null | undefined;
  latitude: number;
  longitude: number;
  icon: string | null;
  category: string;
}

export interface GeoCacheResponse {
  address: NominatimResponse;
  favorite?: Favorite;
}

// TypeScript Interface for Reverse Geocoding Response
export interface NominatimResponse {
  shop?: string | null | undefined;
  leisure?: string | null | undefined;
  house_number?: string | null | undefined;
  road: string;
  neighbourhood?: string | null | undefined;
  suburb?: string | null | undefined;
  county: string;
  town? : string | null | undefined;
  city?: string | null | undefined;
  village?: string | null | undefined;
  municipality?: string | null | undefined;
  state: string;
  'ISO3166-2-lvl4': string;
  postcode: string;
  country: string;
  country_code: string;
}

export interface NominatimRequest {
  latitude: number;
  longitude: number;
}
