﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Photon.Pun;
using Photon.Realtime;
using TMPro;

public class GameLauncher : MonoBehaviourPunCallbacks {

	public CloudRegion cloudRegion;

	string _gameVersion = "1";

	public GameObject testPlayer;
	public bool testPlay = false;

	public int maxPlayersPerRoom = 8;

	public TMP_InputField classIDField;
	public TMP_Text joinErrorMessage;

	public LobbyCanvasHandler handler;
	public TrackManagerScript manager;
	public RacerLobbyUI racerLobbyUI;

	public float matchStartTime = -1f;

	//public GameGenerator gameGenerator;

	public enum CloudRegion {
		USEast, USWest, Europe, CanadaEast
	}


	public Dictionary<CloudRegion, string> cloudRegionTokens = new Dictionary<CloudRegion, string>() {
		{ CloudRegion.USEast, "us" },
		{ CloudRegion.USWest, "usw" },
		{ CloudRegion.Europe, "eu" },
		{ CloudRegion.CanadaEast, "cae" },
	};

	void Awake() {
		PhotonNetwork.AutomaticallySyncScene = true;

		string token = "us";
		if(cloudRegionTokens.TryGetValue(cloudRegion, out token))
			((ServerSettings)Resources.Load("PhotonServerSettings", typeof(ServerSettings))).AppSettings.FixedRegion = token;

	}

	public void Connect() {
		if (PhotonNetwork.IsConnected) {
			PhotonNetwork.JoinRandomRoom();
		}
		else {
			((ServerSettings)Resources.Load("PhotonServerSettings", typeof(ServerSettings))).AppSettings.AppVersion = _gameVersion;
			//PhotonNetwork.GameVersion = _gameVersion;
			PhotonNetwork.ConnectUsingSettings();
		}
	}

	public override void OnConnectedToMaster() {
		Debug.Log("OnConnectedToMaster() was called by PUN");
		PhotonNetwork.JoinRandomRoom();
	}


	public override void OnDisconnected(DisconnectCause cause) {
		Debug.LogWarningFormat("OnDisconnected() was called by PUN with reason {0}", cause);
		GameErrorLogger.WriteToLog("OnDisconnected() was called by PUN with reason " + cause);
	}

	public override void OnJoinRandomFailed(short returnCode, string message) {
		Debug.Log("OnJoinRandomFailed() was called by PUN. No random room available, so we create one.\nCalling: PhotonNetwork.CreateRoom");
		GameErrorLogger.WriteToLog("OnJoinRandomFailed() was called by PUN. No random room available, so we create one.\nCalling: PhotonNetwork.CreateRoom");
		// #Critical: we failed to join a random room, maybe none exists or they are all full. No worries, we create a new room.
		PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = (byte)maxPlayersPerRoom });
	}

	public override void OnJoinedRoom() {
		Debug.Log("Region: " + PhotonNetwork.CloudRegion);
		Debug.Log("OnJoinedRoom() called by PUN. Now this client is in a room.");
		if (testPlay && testPlayer != null) {
			//GameObject.Instantiate (testPlayer, new Vector3 (0, 200, 0), Quaternion.identity);
		} else {
			if (PhotonNetwork.IsMasterClient) {
				//int randomSeed = gameGenerator.GenerateSeed();
				//gameGenerator.SendRandomSeed(randomSeed);
			}
			Debug.Log ("yoyoyo");
			manager.guiActive = true;
			PhotonNetwork.Instantiate ("Base Racer", manager.racerSpots.GetChild (PhotonNetwork.LocalPlayer.ActorNumber-1).position, manager.trackStart.rotation);
			//PhotonNetwork.SendRate = 7;
		}
	}

	public void Submit() {
		_gameVersion = classIDField.text.ToUpper();
		print (_gameVersion);
		if(_gameVersion.Length < 7) {
			joinErrorMessage.gameObject.SetActive(true);
			return;
		}
		joinErrorMessage.gameObject.SetActive(false);
		((ServerSettings)Resources.Load("PhotonServerSettings", typeof(ServerSettings))).AppSettings.AppVersion = _gameVersion;
		//PhotonNetwork.GameVersion = _gameVersion;
		Connect();
		handler.SetInLobbyCanvasActive();
	}

	public float GetMatchStartTime() {
		return matchStartTime;
	}

	public void StartMatch() {
		if (PhotonNetwork.IsMasterClient) {
			SceneManager.LoadScene (manager.selectedLevel);
		}
	}

	// Should only happen if the host is by themselves
	public void ResetMatchStartTime () {
		matchStartTime = -1f;
		PhotonGameDebugger.IncrementNumberOfMessages("match start time");
		photonView.RPC("SetMatchStartTime", RpcTarget.AllBuffered, -1f, false);
		Debug.LogError ("hit reset");
	}

	[PunRPC]
	public void SetMatchStartTime (float sendTime, float startTime, bool addTime) {

		Debug.LogError ("Photon Time: " + PhotonNetwork.Time.ToString () + ", Start Time: " + startTime.ToString ());

		matchStartTime = startTime;

		if (startTime == -1f) {
			racerLobbyUI.cancelCountdown = true;
			Debug.LogError ("Canceled 01");
		} else if (addTime) {
			Debug.LogError ("Adding time");
		} else if (sendTime < startTime) {
			Debug.LogError ("Run Countdown 01");
			StartCoroutine (racerLobbyUI.CountdownToStart ());
		} else if (sendTime >= startTime) {
			Debug.LogError ("Failed");
		}
	}

	[PunRPC]	
	public void BeginMatch (float beginTime) {
		matchStartTime = beginTime;
		if (PhotonNetwork.Time < beginTime) {
			Debug.LogError ("Run Countdown 02");
			StartCoroutine (racerLobbyUI.BeginMatchCountdown ());
		}
	}
}

