using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using Assets.Scripts;

public class GameManager : MonoBehaviour
{
	public static Dialogues Dialogues;
	public UILabel SubtitlesLabel;
	public UISprite TvSprite;
    public static bool isPause = false;
    public int deaths = 0;
    public int team = 0;

    private Vector3 moveInputDirection = Vector3.zero;
    
	public Traveller currentPlayer;

	public static System.Type[] encounter; 
	public static System.Type[] trapsEncounters; 
	public static System.Type[] hintEncounters; 

	public DeathCounter BlackboardCounter;

	List<Instruction> InstructionQueue = new List<Instruction>();
	int CurrentInstruction = 0;
	bool audioShouldPlay = false;
	float audioDelay = 0f;
	float inputDelay = 0f;


	public UISprite bigMapLever;
	public UISprite dangerousMapLever;
	public UISprite resetMapLever;
	public bool bigMap = false;
	public bool dangerousMap = false;

	public bool victory = false;
	private SubjectiveDirection lastMove = SubjectiveDirection.None;


    // Use this for initialization
    void Start()
    {
		Dialogues = this.GetComponent<Dialogues> ();
		SubtitlesLabel.text = "";

		encounter = System.Reflection.Assembly.GetExecutingAssembly().GetTypes();
		trapsEncounters = encounter.Where (e => e.IsSubclassOf (typeof(TrapEncounter))).ToArray ();
		hintEncounters = encounter.Where (e => e.IsSubclassOf (typeof(AudioEncounter)) ||
		                                       e.IsSubclassOf (typeof(TextEncounter)) ||
		                					   e.IsSubclassOf (typeof(GraphicEncounter))).ToArray ();


        Restart();




    }

    void Restart()
    {
        deaths = 0;
        team = 0;
        
        Map.Instance.ReInit(bigMap,dangerousMap);

		victory = false;

		ButtonPressed ();
    }

    // Update is called once per frame
    void Update()
    {
        //if (isPause && Input.GetKey(KeyCode.Escape))
        //{
        //    Application.Quit();
        //}
        //if (Input.GetButtonUp("Pause"))
        //{
        //    isPause = !isPause;
        //    AudioSource audio = Camera.main.gameObject.GetComponent<AudioSource>();
        //    if (isPause)
        //        audio.Pause();
        //    else
        //        audio.Play();

        //}
        //if (isPause)
        //{
        //    return;
        //}

        // TODO: movement
        // maze creation algorythm got reverse values - up/w is going south with actual settings
        //moveInputDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

		HandleInput();

        // TODO: choose action (sacrifice, try all)

		if (audioShouldPlay && !Camera.main.audio.isPlaying && audioDelay <= 0f) {
			audioShouldPlay = false;
			Invoke ("ChangeInstruction", 0.5f);

		}
		if (audioDelay > 0) {
			audioDelay -= Time.deltaTime;
		}
		if (inputDelay > 0) {
			inputDelay -= Time.deltaTime;
		}
    }

	void HandleInput()
	{
		if (currentPlayer == null || inputDelay > 0) 
		{
			return;
		}
		inputDelay = 0.0f;
		if(Input.GetKeyDown(KeyCode.UpArrow))
		{
			TryToMove(SubjectiveDirection.Forward);
		}
		else if(Input.GetKeyDown(KeyCode.DownArrow))
		{
			TryToMove(SubjectiveDirection.TurnBack);
		}
		else if(Input.GetKeyDown(KeyCode.LeftArrow))
		{
			TryToMove(SubjectiveDirection.Left);
		}
		else if(Input.GetKeyDown(KeyCode.RightArrow))
		{
			TryToMove(SubjectiveDirection.Right);
		}
	}

	void TryToMove(SubjectiveDirection direction)
	{
		if(currentPlayer.IsSubjectiveMovePossible(direction) == true)
		{
			lastMove = direction;
			currentPlayer.SubjectiveMove(direction);
		}
	}

	bool VictoryRequirement()
	{
		return false;
	}

	public void HandleArrival(int x, int y, List<Instruction> greetings = null) 
	{
		System.Random rand = new System.Random ();
		var index = 0;
		CurrentInstruction = 0;
		InstructionQueue.Clear ();
		if (greetings != null) InstructionQueue.AddRange (greetings);
		if (lastMove != SubjectiveDirection.None) {
			switch(lastMove) {
				case SubjectiveDirection.Forward : {
					index = rand.Next() % Dialogues.ArchitectGoForward.Length;
					InstructionQueue.Add(new Instruction {
						Message = Dialogues.ArchitectGoForward[index],
						Sound = Dialogues.ArchitectGoForwardAudio[index],
					}); break;
				}
				case SubjectiveDirection.Left : {
					index = rand.Next() % Dialogues.ArchitectGoLeft.Length;
					InstructionQueue.Add(new Instruction {
						Message = Dialogues.ArchitectGoLeft[index],
						Sound = Dialogues.ArchitectGoLeftAudio[index],
					}); break;
				}
				case SubjectiveDirection.Right : {
					index = rand.Next() % Dialogues.ArchitectGoRight.Length;
					InstructionQueue.Add(new Instruction {
						Message = Dialogues.ArchitectGoRight[index],
						Sound = Dialogues.ArchitectGoRightAudio[index],
					}); break;
				}
				case SubjectiveDirection.TurnBack : {
					index = rand.Next() % Dialogues.ArchitectMoveBack.Length;
					InstructionQueue.Add(new Instruction {
						Message = Dialogues.ArchitectMoveBack[index],
						Sound = Dialogues.ArchitectMoveBackAudio[index],
					}); break;
				}
			}
		}

		Map.Instance.getFieldOfMap(currentPlayer.currentPlayerPosition.x, currentPlayer.currentPlayerPosition.y).numberOfVisits++;
		Map.Instance.getFieldOfMap(currentPlayer.currentPlayerPosition.x, currentPlayer.currentPlayerPosition.y).lastTeamNumber = team;



		Camera.main.audio.Stop ();

		var field = Map.Instance.getFieldOfMap (x, y);

		if (field.fieldType == Field.FieldType.Empty)
		{
			TvSprite.spriteName = "tv_nothing";
		}
		if (field.fieldType == Field.FieldType.Exit) 
		{
			CurrentInstruction = 0;

			InstructionQueue.Clear ();
			index = Random.Range(0, Dialogues.TravellerExit.Length);
			InstructionQueue.Add (new Instruction{
				
				Message = Dialogues.TravellerExit[index],
				Sound = Dialogues.TravellerExitAudio[index]
				
			});
			index = Random.Range(0, Dialogues.Victory.Length);
			InstructionQueue.Add (new Instruction{
				
				Message = Dialogues.Victory[index],
				Sound = Dialogues.VictoryAudio[index]
					
			});
			Camera.main.audio.Stop ();
			ChangeInstruction ();

			currentPlayer = null;
			victory = true;

		} else if (field.fieldType == Field.FieldType.Encounter && field.Encounter != null) {
			Instruction instruction = new Instruction ();
			if (field.Encounter.Message.Length > 0) {
				index = rand.Next () % field.Encounter.Message.Length;
				instruction.Message = field.Encounter.Message [index];
				instruction.Sound = field.Encounter.SoundName [index];
			} else {
				instruction.Message = "";
				instruction.Sound = null;
			}
			InstructionQueue.Add (instruction);
			TvSprite.spriteName = field.Encounter.TvPrefabName;
			if (field.Encounter is TrapEncounter) {

				deaths++;
				BlackboardCounter.createLine ();
				currentPlayer = null;
				field.Init (Field.FieldType.Encounter, new Dead ());

				var indexDeath = rand.Next() % Dialogues.ArchitectDeath.Length;
				InstructionQueue.Add(new Instruction {
					Message = Dialogues.ArchitectDeath[indexDeath],
					Sound = Dialogues.ArchitectDeathAudio[indexDeath]});

				ChangeInstruction ();
				return;
			}
		} 

		if(!victory) InstructionQueue.Add (GetDirectionInstruction());
		var indexQuestion = rand.Next() % Dialogues.TravellerQuestion.Length;
		var whatDoWeDoNow = new Instruction {
			Message = Dialogues.TravellerQuestion[indexQuestion],
			Sound = Dialogues.TravellerQuestionAudio[indexQuestion],
		};
		
		InstructionQueue.Add(whatDoWeDoNow);
		
		ChangeInstruction();
	}

	public void ChangeInstruction() {

		if (CurrentInstruction >= InstructionQueue.Count) {
			SubtitlesLabel.text = "";
			return;
		}

		SubtitlesLabel.text = InstructionQueue [CurrentInstruction].Message;
		if (InstructionQueue [CurrentInstruction].Sound != null) 
		{
			Camera.main.audio.clip = InstructionQueue [CurrentInstruction].Sound;
			Camera.main.audio.Play ();
		}
		audioDelay = 3f;
		audioShouldPlay = true;
		CurrentInstruction++;

	}

	public Instruction GetDirectionInstruction() {
		System.Random rand = new System.Random ();
		int index = 0;
		Instruction instruction = new Instruction ();

		if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Left)) {
			if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Forward)) {
					if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Right)) {
							index = rand.Next () % Dialogues.TravellerCrossroadAll.Length;
							instruction.Message = Dialogues.TravellerCrossroadAll [index];
							instruction.Sound = Dialogues.TravellerCrossroadAllAudio [index];
					} else {
							index = rand.Next () % Dialogues.TravellerCrossroadLeft.Length;
							instruction.Message = Dialogues.TravellerCrossroadLeft [index];
							instruction.Sound = Dialogues.TravellerCrossroadLeftAudio [index];
					}
			} else {
					if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Right)) {
							index = rand.Next () % Dialogues.TravellerCrossroadT.Length;
							instruction.Message = Dialogues.TravellerCrossroadT [index];
							instruction.Sound = Dialogues.TravellerCrossroadTAudio [index];
					} else {
							index = rand.Next () % Dialogues.TravellerTurnLeft.Length;
							instruction.Message = Dialogues.TravellerTurnLeft [index];
							instruction.Sound = Dialogues.TravellerTurnLeftAudio [index];
					}
			}
		} else {
			if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Forward)) {
				if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Right)) {
					index = rand.Next() % Dialogues.TravellerCrossroadRight.Length;
					instruction.Message = Dialogues.TravellerCrossroadRight[index];
					instruction.Sound = Dialogues.TravellerCrossroadRightAudio[index];
				}
				else {
					index = rand.Next() % Dialogues.TravellerStraightAhead.Length;
					instruction.Message = Dialogues.TravellerStraightAhead[index];
					instruction.Sound = Dialogues.TravellerStraightAheadAudio[index];
				}
			}
			else {
				if (currentPlayer.IsSubjectiveMovePossible (SubjectiveDirection.Right)) {
					index = rand.Next() % Dialogues.TravellerTurnRight.Length;
					instruction.Message = Dialogues.TravellerTurnRight[index];
					instruction.Sound = Dialogues.TravellerTurnRightAudio[index];
				}
				else {
					index = rand.Next() % Dialogues.TravellerDeadEnd.Length;
					instruction.Message = Dialogues.TravellerDeadEnd[index];
					instruction.Sound = Dialogues.TravellerDeadEndAudio[index];
				}
			}
		}

		return instruction;
	}

	public void ButtonPressed() {
		if (currentPlayer != null)
						return;

		if (victory == true) 
		{
			Restart();
			return;
		}
		lastMove = SubjectiveDirection.None;
		currentPlayer = new Traveller();
		currentPlayer.DropInLabirynth();
		currentPlayer.ParentGameManager = this;
		
		System.Random rand = new System.Random ();
		var indexQuestion = rand.Next() % Dialogues.TravellerGreetings.Length;
		var greetings = new Instruction {
			Message = Dialogues.TravellerGreetings[indexQuestion],
			Sound = Dialogues.TravellerGreetingsAudio[indexQuestion],
		};
		indexQuestion = rand.Next() % Dialogues.ArchitectGreetings.Length;
		var greetingsArch = new Instruction {
			Message = Dialogues.ArchitectGreetings[indexQuestion],
			Sound = Dialogues.ArchitectGreetingsAudio[indexQuestion],
		};

		HandleArrival (currentPlayer.currentPlayerPosition.x, currentPlayer.currentPlayerPosition.y, new List<Instruction>(){greetings, greetingsArch});

	}

	public void BigMapLeverPressed() {
		bigMap = !bigMap;

		CurrentInstruction = 0;
		InstructionQueue.Clear ();

		if (bigMap) 
		{
			bigMapLever.spriteName = "lever_2";

			InstructionQueue.Add (new Instruction{
				
				Message = Dialogues.BigMapOn[0],
				Sound = null
					
			});
		} 
		else 
		{
			bigMapLever.spriteName = "lever_1";

			InstructionQueue.Add (new Instruction{
				
				Message = Dialogues.BigMapOff[0],
				Sound = null
					
			});

		}

		Camera.main.audio.Stop ();
		ChangeInstruction ();
	}

	public void DangerousMapLeverPressed() {
		dangerousMap = !dangerousMap;

		CurrentInstruction = 0;
		InstructionQueue.Clear ();

		if (dangerousMap) 
		{
			dangerousMapLever.spriteName = "lever_2";

			InstructionQueue.Add (new Instruction{
				
				Message = Dialogues.DangerousMapOn[0],
				Sound = null
					
			});
		} 
		else 
		{
			dangerousMapLever.spriteName = "lever_1";

			InstructionQueue.Add (new Instruction{
				
				Message = Dialogues.DangerousMapOff[0],
				Sound = null
					
			});
		}

		Camera.main.audio.Stop ();
		ChangeInstruction ();
	}

	public void ResetMapLeverPressed() {
		currentPlayer = null;
		Restart ();
		resetMapLever.spriteName = "lever_2";
		Invoke ("DisableMapLeverPressed", 0.5f);

		CurrentInstruction = 0;
		int index = Random.Range(0, Dialogues.ResetMap.Length);

		InstructionQueue.Insert (0 ,new Instruction{

			Message = Dialogues.ResetMap[index],
			Sound = null

		});
		Camera.main.audio.Stop ();
		ChangeInstruction ();
	}

	public void DisableMapLeverPressed() 
	{
		resetMapLever.spriteName = "lever_1";
	}

	public void TvPressed() {
		CurrentInstruction = 0;
		ChangeInstruction ();
	}

	public void DoorPressed() {
		Application.LoadLevel ("Outro");
	}
}
