import { PollingEntity } from "./../entities/PollingEntity";
import { SessionStorage } from "quasar";
import ApplicationConfigEntity from "src/entities/ApplicationConfigEntity";
import { HttpProtocol } from "src/entities/HttpProtocol";
import { ModeEntity } from "src/entities/ModeEntity";
import { PlanEntity } from "src/entities/PlanEntity";
import { SignalSourceEntity } from "src/entities/SignalSourceEntity";
import ClientConnection from "./ClientConnection";
import EventBus, { EventNamesDefine } from "./EventBus";

export default class GlobalData {
  getSignalSource(uuid: string) {
    return this.signal_source.find((item) => item && item.uuid == uuid);
  }
  private static _instance: GlobalData | null = null;

  public static get kWebsocketResource() {
    return "/media_player/control";
  }
  public static get kDefaultWebsocektPort() {
    return 61428;
  }

  public static get kDefaultHttpPort() {
    return 80;
  }

  private _current_client_name = "";

  public static getInstance() {
    if (!GlobalData._instance) {
      GlobalData._instance = new GlobalData();
    }
    return GlobalData._instance;
  }

  private _application_config: ApplicationConfigEntity =
    new ApplicationConfigEntity();

  public get applicationConfig() {
    return this._application_config;
  }

  public set applicationConfig(
    config: ApplicationConfigEntity | null | undefined
  ) {
    if (config) {
      this._application_config = config;
      try {
        this._application_config.ip_list = JSON.parse(
          (this._application_config.ip_list ?? []).toString()
        );
      } catch (e) {
        console.log(e);
      }
    }
  }

  clients: Map<string, ClientConnection> = new Map<string, ClientConnection>();

  _signal_source_groups: any[] = [];

  public get signal_source_groups() {
    return this._signal_source_groups;
  }

  public set signal_source_groups(signal_source_groups: any[]) {
    this._signal_source_groups = signal_source_groups;
  }

  _signal_sources: SignalSourceEntity[] = [];

  public get signal_source() {
    return this._signal_sources;
  }

  public set signal_source(sources: SignalSourceEntity[]) {
    this._signal_sources = sources;
  }

  _mode_groups: any[] = [];

  public get mode_groups() {
    return this._mode_groups;
  }

  public set mode_groups(mode_groups: any[]) {
    this._mode_groups = mode_groups;
  }

  _modes: ModeEntity[] = [];

  public get modes() {
    return this._modes;
  }

  public set modes(modes: ModeEntity[]) {
    this._modes = modes;
  }

  _plan_groups: any[] = [];

  public get plan_groups() {
    return this._plan_groups;
  }

  public set plan_groups(plan_groups: any[]) {
    this._plan_groups = plan_groups;
  }

  _plans: PlanEntity[] = [];

  public get plans() {
    return this._plans;
  }

  public set plans(plans: PlanEntity[]) {
    this._plans = plans;
  }

  _pollings: PollingEntity[] = [];

  public get pollings() {
    return this._pollings;
  }

  public set pollings(pollings: PollingEntity[]) {
    this._pollings = pollings;
  }

  constructor() {
    const url: string | null = SessionStorage.getItem("url");
    let name: string | null = SessionStorage.getItem("name");
    let user_name: string | null = SessionStorage.getItem("user_name");
    let password: string | null = SessionStorage.getItem("password");

    if (url) {
      name = name ?? window.location.hostname;
      user_name = user_name ?? "";
      password = password ?? "";

      this._current_client_name = name;
      this.addClient(
        this._current_client_name,
        new ClientConnection(url, user_name, password)
      );
    }

    EventBus.getInstance().on(EventNamesDefine.WebSocketClose, (connection) =>
      this._onWebSocketClose(connection)
    );
    EventBus.getInstance().on(EventNamesDefine.WebSocketError, (connection) =>
      this._onWebSocketError(connection)
    );

    EventBus.getInstance().on(
      EventNamesDefine.WebSocketConnected,
      (connection) => this._onWebSocketConnected(connection)
    );
  }

  private _onWebSocketClose(connection: ClientConnection) {
    if (this.getCurrentClient() == connection) {
      EventBus.getInstance().emit(
        EventNamesDefine.CurrentConnectDisconnect,
        connection
      );
    }
  }
  private _onWebSocketError(connection: ClientConnection) {
    if (this.getCurrentClient() == connection) {
      EventBus.getInstance().emit(
        EventNamesDefine.CurrentConnectDisconnect,
        connection
      );
    }
  }
  private _onWebSocketConnected(connection: ClientConnection) {
    if (this.getCurrentClient() == connection) {
      EventBus.getInstance().emit(
        EventNamesDefine.CurrentConnectConnected,
        connection
      );
    }
  }

  public getClient(name: string | null) {
    if (name) {
      return this.clients.get(name);
    }
  }

  public getCurrentClientName() {
    return this._current_client_name;
  }

  public setCurrentClientName(name: string) {
    this._current_client_name = name;
  }

  public getCurrentClient() {
    return this.getClient(this._current_client_name);
  }

  public clearClients() {
    for (const item of this.clients) {
      if (item && item[1]) {
        item[1]?.destory();
        (<any>item[1]) = null;
      }
    }
    this.clients.clear();
    this.clients = new Map<string, ClientConnection>();
  }

  public createCurrentRequestUrl() {
    let client = this.getCurrentClient();
    if (client) {
      let url = new URL(client.url);
      url.port =
        this.applicationConfig?.httpserver_port ??
        HttpProtocol.DefaultHttpPort.toString();
      url.protocol = "http:";
      return url;
    }
    return null;
  }

  public addClient(name: string | null, client: ClientConnection) {
    if (name) {
      this.clients.set(name, client);
    }
  }

  removeClient(name: string | null) {
    if (name) {
      const connection = this.clients.get(name);
      this.clients.delete(name);
      connection?.destory();
    }
  }
}
