import { Component, OnInit, OnDestroy, inject } from '@angular/core';
import { Editor } from 'ngx-editor';
import { Npc, Npcs } from 'src/interfaces/interfaces';
import { DataService } from 'src/services/data/data.service';

@Component({
  selector: 'app-journal-npcs',
  templateUrl: './journal-npcs.component.html',
  styleUrl: './journal-npcs.component.scss',
})
export class JournalNpcsComponent {
  shortEditor: Editor = new Editor();
  longEditor: Editor = new Editor();
  toolbar: any = [
    // default value
    ['bold', 'italic'],
    ['bullet_list'],
    [{ heading: ['h3', 'h4', 'h5', 'h6'] }],
  ];

  public showShortDescription: boolean = false;

  /** Used to show the interactale form or the display version of an entry. */
  public isInEditMode = false;

  /** The index of the currently active entry */
  public currentIndex: number = 0;
  private backupIndex: number = -1;
  public currentType: string = 'companions';

  /** Indicates, if the currentEntry is a newly generated one that is still not saved. */
  public isNewNpc = false;
  public npcsIsEmpty = true;

  /**The array of JournalEntries, synched to the   */
  public npcs: Npcs = {
    companions: [],
    allies: [],
    enemies: [],
    others: [],
  };

  /** Holds the data for the current entry */
  public currentNpc: Npc = {
    name: '',
    shortDescription: '',
    longDescription: '',
  };

  private dataService: DataService = inject(DataService);

  ngOnInit(): void {
    this.npcs = this.dataService.npcs;
    this.searchForNextNpc();
  }

  // FUNCTIONS

  public selectNpc(index: number, type: string): void {
    this.currentIndex = index;
    this.currentType = type;
    this.currentNpc = this.getNpc();
    this.isNewNpc = false;
    this.isInEditMode = false;
  }

  public addNpc(type: string): void {
    this.currentNpc = {
      name: '',
      shortDescription: '',
      longDescription: '',
    };
    this.currentType = type;
    this.isInEditMode = true;
    this.isNewNpc = true;
    this.backupIndex = this.currentIndex;
    this.currentIndex = -1;
    this.npcsIsEmpty = false;
  }

  /**
   * Switches to the edit mode for the current entry.
   */
  public editNpc(): void {
    this.isInEditMode = true;
  }

  public saveNpc(): void {
    if (this.isNewNpc) {
      // Prepend the new Npc
      this.getList().unshift(this.currentNpc);
      this.isNewNpc = false;
      this.currentIndex = 0;
    }
    this.isInEditMode = false;
    this.getList()[this.currentIndex] = this.currentNpc;
    this.uploadNpcs();
  }

  public discardNpc(): void {
    if (this.isNewNpc) {
      this.currentIndex = this.backupIndex;
      this.isNewNpc = false;
    }
    if (this.getList().length > 0) {
      // Reset the currentEntry to the last saved version
      this.currentNpc = this.getNpc();
    } else {
      this.searchForNextNpc();
    }
    this.isInEditMode = false;
  }

  /**
   * Delets an npc in the current list at the current index and uploads the result to the server.
   */
  public deleteNpc(): void {
    this.getList().splice(this.currentIndex, 1);
    if (this.getList().length === 0) {
      this.searchForNextNpc();
    } else {
      this.currentIndex = Math.max(this.currentIndex - 1, 0);
      this.currentNpc = this.getNpc();
    }
    this.uploadNpcs();
  }

  // Utility functions

  private getList(): Npc[] {
    switch (this.currentType) {
      case 'companions':
        return this.npcs.companions;
      case 'allies':
        return this.npcs.allies;
      case 'enemies':
        return this.npcs.enemies;
      case 'others':
        return this.npcs.others;
      default:
        return this.npcs.allies;
    }
  }

  public getNpc(): Npc {
    switch (this.currentType) {
      case 'companions':
        return JSON.parse(
          JSON.stringify(this.npcs.companions[this.currentIndex]),
        );
      case 'allies':
        return JSON.parse(JSON.stringify(this.npcs.allies[this.currentIndex]));
      case 'enemies':
        return JSON.parse(JSON.stringify(this.npcs.enemies[this.currentIndex]));
      case 'others':
        return JSON.parse(JSON.stringify(this.npcs.others[this.currentIndex]));
      default:
        return JSON.parse(JSON.stringify(this.npcs.allies[this.currentIndex]));
    }
  }

  private searchForNextNpc(): void {
    let notFound = true;
    ['companions', 'allies', 'enemies', 'others'].forEach((type) => {
      if (this.npcs[type].length > 0 && notFound) {
        this.currentType = type;
        this.currentIndex = 0;
        this.currentNpc = this.getNpc();
        notFound = false;
      }
    });
    this.npcsIsEmpty = notFound;
  }

  private uploadNpcs(): void {
    this.dataService.npcs = this.npcs;
  }
}
