import { Player } from "../entities/Player";
import { SpriteWithDynamicBody } from "../../types";
import { GameScene } from "./GameScene";
import { EventBus } from "../EventBus";
import { Mountain } from "../entities/Mountain";
import { TreeFactory } from "../entities/Tree";
import { FlagsFactory } from "../entities/Flags";
import { RightWall } from "../entities/RightWall";
import { PlayButton } from "../entities/PlayButton";

class PlayScene extends GameScene {

  player: Player | null = null;
  mountain: Mountain | null = null;
  rightWall: Phaser.GameObjects.TileSprite | null = null;
  trees: Phaser.Physics.Arcade.Group | null = null;
  flags: Phaser.Physics.Arcade.Group | null = null;
  flagsBadAreas: Phaser.Physics.Arcade.Group | null = null;

  treeFactory: TreeFactory = new TreeFactory(this);
  flagsFactory: FlagsFactory = new FlagsFactory(this);

  restartText: Phaser.GameObjects.Image | undefined;
  playButton_: Phaser.GameObjects.Image | undefined;
  playButton: PlayButton | undefined;

  score: number = 0;
  collectedFlags: number = 0;
  scoreInterval: number = 100;
  scoreDeltaTime: number = 0;

  treeSpawnInterval: number = 3000;
  treeSpawnTime: number = 0;

  flagsSpawnInterval: number = 5000;
  flagsSpawnTime: number = 0;

  gameSpeed: number = 2;
  gameSpeedModifier: number = 1;
  cursors: Phaser.Types.Input.Keyboard.CursorKeys | undefined;

  // isPlayButtonVisible: boolean = true;

  progressSound: Phaser.Sound.HTML5AudioSound | undefined;
  progressSoundShiny: Phaser.Sound.HTML5AudioSound | undefined;

  lastTimeFlagCollected: number = 0;
  flagCollectedInterval: number = 500;

  constructor() {
    super("PlayScene");
  }

  create() {
    this.cursors = this.input.keyboard?.createCursorKeys();

    this.createMountain();
    this.createPlayer();
    this.createRightWall();

    this.createTrees();
    this.handleTreeCollisions();
    this.handleRightWallCollision();

    this.createFlags();
    this.handleFlagsCollisions();

    // this.createShinyStars();
    // this.handleShinyStarCollisions();

    this.createPlayButton();


    this.handleGameRestartSetup();

    this.progressSound = this.sound.add("progress", { volume: 0.2 }) as Phaser.Sound.HTML5AudioSound;
    this.progressSoundShiny = this.sound.add("progress", { volume: 0.5 }) as Phaser.Sound.HTML5AudioSound;
    EventBus.emit('current-scene-ready', this);
    // this.spawnTree();
    // this.spawnFlags();

    if (this.scale.width < 600) {
      this.gameSpeed = 3;
    } else if (this.scale.width < 800) {
      this.gameSpeed = 3;
    } else if (this.scale.width < 1200) {
      this.gameSpeed = 4;
    } else if (this.scale.width < 1600) {
      this.gameSpeed = 4;
    } else if (this.scale.width < 2000) {
      this.gameSpeed = 4;
    } else if (this.scale.width < 2500) {
      this.gameSpeed = 5;
    } else {
      this.gameSpeed = 6;
    }
  }

  update(time: number, delta: number): void {
    if (!this.isGameRunning) return;
    EventBus.emit('play-scene-updated', this);

    if (this.player && this.rightWall) {
      const isPlayerTouchingGround = this.physics.overlap(this.player, this.rightWall);
      this.player.canGoRight = !isPlayerTouchingGround;
    }

    this.treeSpawnTime += delta;
    this.flagsSpawnTime += delta;

    this.scoreDeltaTime += delta;

    if (this.scoreDeltaTime >= this.scoreInterval) {
      this.score++;
      this.scoreDeltaTime = 0;

      // if (this.score % 100 === 0) {
      //   this.gameSpeedModifier += 0.2;
      //   this.tweens.add({
      //     targets: this.scoreText,
      //     duration: 100,
      //     repeat: 3,
      //     alpha: 0,
      //     yoyo: true
      //   });
      // }
    }

    if (this.treeSpawnTime >= this.treeSpawnInterval) {
      this.spawnTree();
      this.treeSpawnTime = 0;
    }

    if (this.flagsSpawnTime >= this.flagsSpawnInterval) {
      this.spawnFlags();
      this.flagsSpawnTime = 0;
    }

    Phaser.Actions.IncY(this.trees?.getChildren() || [], -this.gameSpeed * this.gameSpeedModifier);
    Phaser.Actions.IncY(this.flags?.getChildren() || [], -this.gameSpeed * this.gameSpeedModifier);
    Phaser.Actions.IncY(this.flagsBadAreas?.getChildren() || [], -this.gameSpeed * this.gameSpeedModifier);

    const score = Array.from(String(this.score), Number);

    for (let i = 0; i < 5 - String(this.score).length; i++) {
      score.unshift(0);
    }

    this.trees?.getChildren().forEach((tree: Phaser.GameObjects.GameObject) => {
      if ((tree as SpriteWithDynamicBody).getBounds().right < 0) {
        this.trees?.remove(tree);
      }
    });

    this.flags?.getChildren().forEach((flags: Phaser.GameObjects.GameObject) => {
      if ((flags as SpriteWithDynamicBody).getBounds().right < 0) {
        this.flags?.remove(flags);
      }
    });

    this.flagsBadAreas?.getChildren().forEach((badArea: Phaser.GameObjects.GameObject) => {
      if ((badArea as SpriteWithDynamicBody).getBounds().right < 0) {
        this.flagsBadAreas?.remove(badArea);
      }
    });
  }

  createPlayer() {
    this.player = new Player(this);
  }

  createMountain() {
    this.mountain = new Mountain(this);
  }

  createRightWall() {
    this.rightWall = new RightWall(this);
  }

  createTrees() {
    this.trees = this.physics.add.group();
  }

  createFlags() {
    this.flags = this.physics.add.group();
    this.flagsBadAreas = this.physics.add.group();
  }

  createPlayButton() {
    this.playButton = new PlayButton(this);
    this.playButton_ = this.playButton.playButton;
  }


  spawnTree() {
    if (!this.trees) return;
    this.treeFactory.create(this.trees);
  }

  spawnFlags() {
    if (!this.flags) return;
    const createdFlags = this.flagsFactory.create(this.flags);
    createdFlags.badAreaLeft && this.flagsBadAreas?.add(createdFlags.badAreaLeft);
    createdFlags.badAreaRight && this.flagsBadAreas?.add(createdFlags.badAreaRight);
  }

  handleGameStart() {
    const rollOutEvent = this.time.addEvent({
      delay: 1000 / 60,
      loop: true,
      callback: () => {
        this.player?.setVelocityX(80);

        rollOutEvent.remove();
        this.player?.setVelocityX(0);
        // this.scoreText.setAlpha(1);
        this.isGameRunning = true;
      }
    });
    // this.playButtonContainer?.setAlpha(0);
    this.playButton?.onGameStart();
  }

  handleGameRestartSetup() {
    this.restartText?.on("pointerdown", () => {
      this.handleGameRestart();
    });
    this.playButton?.playButton?.on("pointerdown", () => {
      if (this.isGameRunning) {
        this.treeCollision();
      } else {
        this.handleGameRestart();
      }
    });
  }

  handleGameRestart() {
    this.physics.resume();
    this.player?.setVelocityY(0);

    this.trees?.clear(true, true);
    this.flags?.clear(true, true);
    this.collectedFlags = 0;
    this.score = 0;

    // this.playButtonContainer?.setAlpha(0);
    // this.isPlayButtonVisible = false;
    this.anims.resumeAll();

    this.isGameRunning = true;

    this.playButton?.onGameStart();

    // this.player?.setTexture("marty-in-plane");
    this.player?.positionOnMountain();



  }

  handleRightWallCollision() {
    // the player should not be able to move past the right wall
    if (!this.player) return;
    if (!this.rightWall) return;
    this.physics.add.collider(this.player, this.rightWall, () => {
      if (this.player) {
        this.player.canGoRight = false;
      }
    });
  }

  treeCollision() {
    this.isGameRunning = false;
    this.physics.pause();
    this.anims.pauseAll();

    this.player?.die();

    this.playButton?.onGameOver();
    // this.playButtonContainer?.setAlpha(1);
    // this.isPlayButtonVisible = true;

    this.treeSpawnTime = 0;
    this.score = 0;
    this.collectedFlags = 0;
    this.scoreDeltaTime = 0;
    this.gameSpeedModifier = 1;

    EventBus.emit('die', this);
  }

  handleTreeCollisions() {
    if (!this.trees) return;
    if (!this.player) return;
    this.physics.add.collider(this.trees, this.player, () => {
      this.treeCollision();
    });
  }

  handleFlagsCollisions() {
    if (!this.flags) return;
    if (!this.flagsBadAreas) return;
    if (!this.player) return;
    this.physics.add.collider(this.flags, this.player, (player, flags) => {
      if ((flags as SpriteWithDynamicBody).getData('collected')) return;
      if (this.time.now - this.lastTimeFlagCollected < this.flagCollectedInterval) return;
      this.lastTimeFlagCollected = this.time.now;
      // flags.destroy();
      (flags as SpriteWithDynamicBody).setData('collected', true);
      // this.score += 40;
      this.collectedFlags++;
      EventBus.emit('flags-collected', this);
      if (this.collectedFlags === 10) {
        EventBus.emit('target-achieved', this);
        this.isGameRunning = false;
        this.playButton?.onFlagsCollected();
        // this.playButtonContainer?.setAlpha(1);
        // this.isPlayButtonVisible = true;
        this.physics.pause();
        this.anims.pauseAll();
      }
      this.progressSound?.play();
    });

    this.physics.add.collider(this.flagsBadAreas, this.player, (player, badArea) => {
      if ((badArea as SpriteWithDynamicBody).getData('collected')) return;
      (badArea as SpriteWithDynamicBody).setData('collected', true);
      if (this.time.now - this.lastTimeFlagCollected < this.flagCollectedInterval) return;
      this.lastTimeFlagCollected = this.time.now;
      if (this.collectedFlags === 0) return;
      this.collectedFlags--;
      EventBus.emit('flags-lost', this);
      this.player?.hitSound?.play();
    });

  }
}

export default PlayScene;
