#define GAMELOOP_DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameLoopState : BaseGameState {
    
    private bool gameOver = false;

    public override void InitState()
    {
        base.InitState();

        this.gameController.CameraController.ChangeState(new GameCameraState());

        this.gameController.UIController.GameplayView.ShowView();

        this.gameController.GameEvents.CallOnGameStarted(this.gameController.DataStorage.CurrentGame);

        var gameCamera = new GameCameraState();
        gameCamera.objectToFollow = this.gameController.Player.transform;
        this.gameController.CameraController.ChangeState(gameCamera);

        this.gameOver = false;

        this.gameController.GameEvents.OnZombieDied += ZombieKilled;
        this.gameController.GameEvents.OnPlayerDied += PlayerDied;
        this.gameController.GameEvents.OnGameWon += PlayerWon;
    }

    public override void UpdateState()
    {
        if (gameOver) return;

        base.UpdateState();

        this.gameController.DataStorage.CurrentGame.SessionTime += TimeSpan.FromSeconds(Time.deltaTime);

        this.UpdatePlayer();

    }

    public override void DeinitState()
    {
        this.gameController.GameEvents.OnZombieDied -= ZombieKilled;
        this.gameController.GameEvents.OnPlayerDied -= PlayerDied;
        this.gameController.GameEvents.OnGameWon -= PlayerWon;

        this.gameController.UIController.GameplayView.HideView();

        GameObject.Destroy(this.gameController.Player.gameObject);
        GameObject.Destroy(this.gameController.MapPortal.gameObject);
        GameObject.Destroy(this.gameController.Antenna.gameObject);

        base.DeinitState();
    }

    private void UpdatePlayer () {

        var horizontal = Input.GetAxis("Horizontal");
        var vertical = Input.GetAxis("Vertical");

        var moveDirection = Quaternion.Euler(0, 45, 0) * new Vector3(-horizontal, 0, -vertical);
        this.gameController.Player.Movement.MoveBy(moveDirection);

        if (Input.GetButton("Fire1")) {
            
            Vector3 aimPosition;
            var lineRay = this.gameController.CameraController.MainCamera.ScreenPointToRay(Input.mousePosition);

            if (Math3d.LinePlaneIntersection(out aimPosition, lineRay.origin, lineRay.direction, Vector3.up, Vector3.up * 0.5f)) {
                var dir = aimPosition - this.gameController.Player.transform.position;
                this.gameController.Player.Movement.RotateTo(dir);
                this.gameController.Player.Shooter.Shoot();
            }
        } else if (Input.GetButton("Grab")) {
            this.gameController.Player.Graber.Grab();
        } else if (Input.GetButton("Drop")) {
            this.gameController.Player.Graber.Drop();
        }
        
    }

    private void ZombieKilled () {
        this.gameController.DataStorage.CurrentGame.ZombiesKilled++;
    }

    private void PlayerWon () {
#if GAMELOOP_DEBUG
        Debug.Log("[Game Loop] Player won after " + this.gameController.DataStorage.CurrentGame.SessionTime.Seconds + " seconds");
#endif
        this.gameController.GameEvents.OnGameWon -= PlayerWon;

        this.gameController.UIController.BlackedView.OnScreenBlacked += OnBlackedPlayerWon;
        this.gameController.UIController.BlackedView.ShowView();
        this.gameController.CameraController.ChangeState(new GameEndedCameraState());
    }

    private void OnBlackedPlayerWon () {

        this.gameController.UIController.BlackedView.OnScreenBlacked -= OnBlackedPlayerWon;
        this.gameController.DataStorage.CurrentGame.SessionState = CurrentGameData.SessionStateEnum.FinishedWithSuccess;
        this.gameController.GameEvents.CallOnGameFinished(this.gameController.DataStorage.CurrentGame);
        this.gameController.ChangeState(new GameEndedState());
    }

    private void PlayerDied () {
#if GAMELOOP_DEBUG
        Debug.Log("[Game Loop] Player died after " + this.gameController.DataStorage.CurrentGame.SessionTime.Seconds + " seconds");
#endif
        this.gameController.GameEvents.OnPlayerDied -= PlayerDied;

        this.gameController.UIController.BlackedView.OnScreenBlacked += OnBlackedPlayerDied;
        this.gameController.UIController.BlackedView.ShowView();
        this.gameController.CameraController.ChangeState(new GameEndedCameraState());
    }

    private void OnBlackedPlayerDied () {
        
        this.gameController.UIController.BlackedView.OnScreenBlacked -= OnBlackedPlayerDied;
        this.gameController.DataStorage.CurrentGame.SessionState = CurrentGameData.SessionStateEnum.FinishedWithFailure;
        this.gameController.GameEvents.CallOnGameFinished(this.gameController.DataStorage.CurrentGame);
        this.gameController.ChangeState(new GameEndedState());
    }
}
