/* eslint-disable no-param-reassign */
import { 
  BroadcastCreatedEvent,
  BroadcastEvent,
  ContextDeleteEvent, 
  ContextQueryEvent, ContextReadBulkEvent, 
  ContextReadEvent, ContextUpdateEvent, 
  IRequestUiMeta, 
  IUrl
} from "@api-client/core/build/browser.js";
import { Events } from "../../events/Events.js";
import { EventTypes } from "../../events/EventTypes.js";
import { StoreBroadcast } from "../../http-client/store/StoreBroadcast.js";
import { PlatformBindings } from "./PlatformBindings.js";
import { ProjectUi } from "../../http-client/store/stores/ProjectUi.js";
import { UrlHistory } from "../../http-client/store/stores/UrlHistory.js";
import { WsHistory } from "../../http-client/store/stores/WsHistory.js";
import { IRequestUiInsertDetail } from "../../events/HttpClientEvents.js";

export abstract class HttpClientStoreBindings extends PlatformBindings {
  urlHistoryChannel = new BroadcastChannel(StoreBroadcast.urlHistory);
 
  abstract initializeStore(): Promise<void>;
  
  abstract wsHistory: WsHistory;
  
  abstract urlHistory: UrlHistory;

  abstract projectUi: ProjectUi;
  
  async initialize(): Promise<void> {
    const target = document.body;
    target.addEventListener(EventTypes.HttpClient.Model.UrlHistory.add, this.addUrlHistoryHandler.bind(this));
    target.addEventListener(EventTypes.HttpClient.Model.UrlHistory.query, this.queryUrlHistoryHandler.bind(this));
    target.addEventListener(EventTypes.HttpClient.Model.UrlHistory.delete, this.deleteUrlHistoryHandler.bind(this));
    target.addEventListener(EventTypes.HttpClient.Model.UrlHistory.clear, this.clearUrlHistoryHandler.bind(this));

    target.addEventListener(EventTypes.HttpClient.Model.WsHistory.add, this.addWsHistoryHandler.bind(this));
    target.addEventListener(EventTypes.HttpClient.Model.WsHistory.query, this.queryWsHistoryHandler.bind(this));
    target.addEventListener(EventTypes.HttpClient.Model.WsHistory.delete, this.deleteWsHistoryHandler.bind(this));
    target.addEventListener(EventTypes.HttpClient.Model.WsHistory.clear, this.clearWsHistoryHandler.bind(this));

    // Request UI
    window.addEventListener(EventTypes.HttpProject.Ui.delete, this.deleteProjectUiHandler.bind(this) as EventListener);
    window.addEventListener(EventTypes.HttpProject.Ui.HttpRequest.set, this.setHttpRequestUiHandler.bind(this) as EventListener);
    window.addEventListener(EventTypes.HttpProject.Ui.HttpRequest.get, this.getHttpRequestUiHandler.bind(this) as EventListener);
    window.addEventListener(EventTypes.HttpProject.Ui.HttpRequest.getBulk, this.getBulkHttpRequestUiHandler.bind(this) as EventListener);
    window.addEventListener(EventTypes.HttpProject.Ui.HttpRequest.delete, this.deleteHttpRequestUiHandler.bind(this) as EventListener);

    this.urlHistoryChannel.addEventListener('message', this.handleUrlHistoryBroadcast.bind(this));
  }

  protected handleUrlHistoryBroadcast(e: MessageEvent): void {
    const event = e.data as BroadcastEvent;
    switch (event.operation) {
      case 'created': this.handleUrlHistoryCreated((event as BroadcastCreatedEvent).data as IUrl); break;
      case 'deleted': this.handleUrlHistoryDeleted(event.key); break;
      case 'cleared': this.handleUrlHistoryCleared(); break;
      default:
    }
  }

  protected handleUrlHistoryCreated(entity: IUrl): void {
    Events.HttpClient.Model.UrlHistory.State.add(entity);
  }

  protected handleUrlHistoryDeleted(url: string): void {
    Events.HttpClient.Model.UrlHistory.State.delete(url);
  }

  protected handleUrlHistoryCleared(): void {
    Events.HttpClient.Model.UrlHistory.State.clear();
  }

  protected addUrlHistoryHandler(event: Event): void {
    const e = event as CustomEvent;
    e.preventDefault();
    e.detail.result = this.urlHistory.add(e.detail.url);
  }

  protected queryUrlHistoryHandler(event: Event): void {
    const e = event as ContextQueryEvent<IUrl>;
    e.preventDefault();
    e.detail.result = this.urlHistory.query(e.detail.term);
  }

  protected deleteUrlHistoryHandler(event: Event): void {
    const e = event as ContextDeleteEvent;
    e.preventDefault();
    e.detail.result = this.urlHistory.delete(e.detail.key);
  }

  protected clearUrlHistoryHandler(event: Event): void {
    const e = event as CustomEvent;
    e.preventDefault();
    e.detail.result = this.urlHistory.clear();
  }

  protected addWsHistoryHandler(event: Event): void {
    const e = event as CustomEvent;
    e.preventDefault();
    e.detail.result = this.wsHistory.add(e.detail.url);
  }

  protected queryWsHistoryHandler(event: Event): void {
    const e = event as ContextQueryEvent<IUrl>;
    e.preventDefault();
    e.detail.result = this.wsHistory.query(e.detail.term);
  }

  protected deleteWsHistoryHandler(event: Event): void {
    const e = event as ContextDeleteEvent;
    e.preventDefault();
    e.detail.result = this.wsHistory.delete(e.detail.key);
  }

  protected clearWsHistoryHandler(event: Event): void {
    const e = event as CustomEvent;
    e.preventDefault();
    e.detail.result = this.wsHistory.clear();
  }

  protected deleteProjectUiHandler(e: ContextDeleteEvent): void {
    e.preventDefault();
    const { key } = e.detail;
    e.detail.result = this.projectUi.clear(key);
  }

  protected setHttpRequestUiHandler(e: ContextUpdateEvent<IRequestUiInsertDetail, IRequestUiMeta>): void {
    e.preventDefault();
    const { item } = e.detail;
    e.detail.result = this.projectUi.set(item.pid, item.id, item.meta);
  }

  protected getHttpRequestUiHandler(e: ContextReadEvent<IRequestUiMeta>): void {
    e.preventDefault();
    const { key, parent } = e.detail;
    e.detail.result = this.projectUi.get(parent as string, key);
  }

  protected getBulkHttpRequestUiHandler(e: ContextReadBulkEvent<IRequestUiMeta | undefined>): void {
    e.preventDefault();
    const { keys, parent } = e.detail;
    e.detail.result = this.projectUi.getBulk(parent as string, keys);
  }

  protected deleteHttpRequestUiHandler(e: ContextDeleteEvent): void {
    e.preventDefault();
    const { key, parent } = e.detail;
    e.detail.result = this.projectUi.delete(parent as string, key);
  }
}
