import type { GameSettings } from '@/scripts/interfaces/GameSettings';
import GameConnection, {
  type GameIdentifier,
  type GameInformationDto,
  type GameEnded,
} from '../signalR/GameConnection';
import { getRandomMovePhrase } from '@/scripts/utils/RandomPlaceMessage';

class LocalGame {
  public player1: GameConnection;
  public player2: GameConnection;
  public currentDescription: string = 'Warte auf Spielaufbau ...';
  private gameId: string = '';
  private botGame = false;

  public gameState: GameInformationDto | undefined;
  public onGameStateChanged?: (gameState: GameInformationDto | undefined) => void;
  public onGameEnded?: (gameEndedInfo: GameEnded) => void;

  constructor() {
    this.player1 = new GameConnection();
    this.player2 = new GameConnection();

    this.player1.onGameStarted = (gameInfo: GameInformationDto) => {
      console.log('Game started for player 1', gameInfo);
      this.gameState = gameInfo;
      this.onGameStateChanged?.(this.gameState);

      this.changePlaceDescription();
    };

    this.player1.onFieldUpdated = (currentState: GameInformationDto) => {
      this.updateState(currentState);
      this.changePlaceDescription();
    };

    this.player1.onGameCreated = (gameIdentifier: GameIdentifier) => {
      this.gameId = gameIdentifier.gameId;
      this.player2.joinGame(gameIdentifier.gameCode);
    };

    this.player2.onGameJoined = (gameIdentifier: GameIdentifier) => {
      this.gameId = gameIdentifier.gameId;
    };

    this.player1.onGameEnded = (gameEndedInfo: GameEnded) => {
      this.onGameEnded?.(gameEndedInfo);
    };
  }

  async start(settings: GameSettings) {
    await this.player1.connect(settings.playerName1);
    await this.player2.connect(settings.playerName2 ?? 'Spieler 2');

    this.botGame = settings.botPlayer2 ?? false;

    await this.player1.createGame(settings.fieldSize);
  }

  async updateState(newState: GameInformationDto) {
    if (this.gameState) {
      this.gameState = newState;
      this.onGameStateChanged?.(this.gameState);
    }
  }

  async drop(index: number) {
    if (this.gameState?.currentTurn == 1) {
      this.player1.drop(this.gameId, index);

      if (this.botGame) {
        const randomDelay = Math.random() * 2000 + 1000;
        setTimeout(() => {
          const botIndex = Math.floor(Math.random() * this.gameState!.currentField.length);
          this.player2.drop(this.gameId, botIndex);
        }, randomDelay);
      }
    } else if(!this.botGame) {
      this.player2.drop(this.gameId, index);
    }
  }

  changePlaceDescription() {
    const playerName =
      this.gameState?.currentTurn == 1 ? this.player1.playerName : this.player2.playerName;
    this.currentDescription = getRandomMovePhrase(playerName);
  }

  async disconnectAll() {
    await this.player1.disconnect();
    await this.player2.disconnect();
  }
}

export default LocalGame;
