import { APIClient } from "./ApiClient";

export interface ServerConfig {
  auth_disabled: boolean;
  local_auth_enabled: boolean;
  oidc_auth_enabled: boolean;
  iso_mimetypes: string[];
  disk_images_mimetypes: string[];
  net_mac_prefix: string;
  builtin_nwfilter_rules: string[];
  nwfilter_chains: string[];
  constraints: ServerConstraints;
}

export interface ServerConstraints {
  iso_max_size: number;
  disk_image_max_size: number;
  vnc_token_duration: number;
  vm_name_size: LenConstraint;
  vm_title_size: LenConstraint;
  group_id_size: LenConstraint;
  memory_size: LenConstraint;
  disk_name_size: LenConstraint;
  disk_size: LenConstraint;
  disk_image_name_size: LenConstraint;
  net_name_size: LenConstraint;
  net_title_size: LenConstraint;
  net_nat_comment_size: LenConstraint;
  dhcp_reservation_host_name: LenConstraint;
  nwfilter_name_size: LenConstraint;
  nwfilter_comment_size: LenConstraint;
  nwfilter_priority: LenConstraint;
  nwfilter_selectors_count: LenConstraint;
  api_token_name_size: LenConstraint;
  api_token_description_size: LenConstraint;
  api_token_right_path_size: LenConstraint;
}

export interface LenConstraint {
  min: number;
  max: number;
}

let config: ServerConfig | null = null;

export interface ServerSystemInfo {
  hypervisor: HypervisorInfo;
  system: SystemInfo;
  components: SysComponent;
  disks: DiskInfo[];
  networks: NetworkInfo[];
}

interface HypervisorInfo {
  type: string;
  hyp_version: number;
  lib_version: number;
  capabilities: string;
  free_memory: number;
  hostname: string;
  node: {
    cpu_model: string;
    memory_size: number;
    number_of_active_cpus: number;
    cpu_frequency_mhz: number;
    number_of_numa_cell: number;
    number_of_cpu_socket_per_node: number;
    number_of_core_per_sockets: number;
    number_of_threads_per_core: number;
  };
}

interface SystemInfo {
  IS_SUPPORTED: boolean;
  SUPPORTED_SIGNALS: string[];
  MINIMUM_CPU_UPDATE_INTERVAL: {
    secs: number;
    nanos: number;
  };
  global_cpu_usage: number;
  cpus: CpuCore[];
  physical_core_count: number;
  total_memory: number;
  free_memory: number;
  available_memory: number;
  used_memory: number;
  total_swap: number;
  free_swap: number;
  used_swap: number;
  uptime: number;
  boot_time: number;
  load_average: SysLoadAverage;
  name: string;
  kernel_version: string;
  os_version: string;
  long_os_version: string;
  distribution_id: string;
  host_name: string;
}

interface CpuCore {
  cpu_usage: number;
  name: string;
  vendor_id: string;
  brand: string;
  frequency: number;
}

interface SysComponent {
  temperature: number;
  max: number;
  critical: number;
  label: string;
}

export interface DiskInfo {
  DiskKind: "HDD" | "SSD";
  name: string;
  file_system: number[];
  mount_point: string;
  total_space: number;
  available_space: number;
  is_removable: boolean;
}

export type NetworkInfo = [string, NetworkDetails];
interface NetworkDetails {
  received: number;
  total_received: number;
  transmitted: number;
  total_transmitted: number;
  packets_received: number;
  total_packets_received: number;
  packets_transmitted: number;
  total_packets_transmitted: number;
  errors_on_received: number;
  total_errors_on_received: number;
  errors_on_transmitted: number;
  total_errors_on_transmitted: number;
  mac_address: number[];
}

interface SysLoadAverage {
  one: number;
  five: number;
  fifteen: number;
}

export interface NetworkHookStatus {
  installed: boolean;
  content: string;
  path: string;
}

export class ServerApi {
  /**
   * Get server configuration
   */
  static async LoadConfig(): Promise<void> {
    config = (
      await APIClient.exec({
        uri: "/server/static_config",
        method: "GET",
      })
    ).data;
  }

  /**
   * Get cached configuration
   */
  static get Config(): ServerConfig {
    if (config === null) throw new Error("Missing configuration!");
    return config;
  }

  /**
   * Get server information
   */
  static async SystemInfo(): Promise<ServerSystemInfo> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: "/server/info",
      })
    ).data;
  }

  /**
   * Get network hook status
   */
  static async NetworkHookStatus(): Promise<NetworkHookStatus> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: "/server/network_hook_status",
      })
    ).data;
  }

  /**
   * Get host supported vCPUs configurations
   */
  static async NumberVCPUs(): Promise<number[]> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: "/server/number_vcpus",
      })
    ).data;
  }

  /**
   * Get host networks card list
   */
  static async GetNetworksList(): Promise<string[]> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: "/server/networks",
      })
    ).data;
  }

  /**
   * Get host networks bridges list
   */
  static async GetNetworksBridgesList(): Promise<string[]> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: "/server/bridges",
      })
    ).data;
  }
}