using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public class MochaParser
{
	public List<PlayerInfo> players;

	public MochaParser()
	{
		players = new List<PlayerInfo> ();
	}

	/*
	 * You need to call this to make an HTTP request.
	 * */
	public IEnumerator MakeRequest(string request)
	{
		using (UnityWebRequest www = UnityWebRequest.Get(request))
		{
			yield return www.SendWebRequest();

			if (www.isNetworkError || www.isHttpError)
			{
				Debug.Log(www.error);
			}
			else
			{
				// Do the parsing.
				Debug.Log(www.downloadHandler.text);
				ParseJsonRaw(www.downloadHandler.text);

				// Or retrieve results as binary data
				byte[] results = www.downloadHandler.data;
			}
		}
	}

	/*
	 * Call this to do all the parsing.
	 * JSON objects will be separated and saved
	 * in a public class variable "players".
	 * */
	public void ParseJsonRaw(string json)
	{
		players = new List<PlayerInfo>();
		string tempjson = "";

		bool ignorequotes = false;
		bool specialchar = false;
		bool insideobject = false;

		foreach (char c in json)
		{
			if (insideobject)
			{
				tempjson += c;
			}

			if (c == '\"')
			{
				if (!specialchar)
				{
					ignorequotes = !ignorequotes;
				}
			}

			if(specialchar)
			{
				specialchar = false;
			}

			if(c == '\\')
			{
				specialchar = true;
			}

			if (!ignorequotes)
			{
				if (c == '{')
				{
					insideobject = true;
					tempjson += c;
				}
				else if (c == '}')
				{
					insideobject = false;
					players.Add(ParseJson(tempjson));
					tempjson = "";
				}
			}
		}
	}

	/*
	 * Don't use this unless you want to experience pain.
	 * It's useless because you can just use the above function.
	 * */
	public PlayerInfo ParseJson(string json)
	{
		return JsonUtility.FromJson<PlayerInfo>(json);
	}

	/*
	 * Call this after parsing if you just want the text
	 * output of the parsed JSON.
	 * */
	public string OutputInfo()
	{
		string output = "";

		foreach (PlayerInfo pi in players)
		{
			output += "Player ID: " + pi.user_id +
				"\t\tUser: " + pi.username +
				"\t\tScore: " + pi.score + "\n";
		}

		return output;
	}


	public string OutputIds()
	{
		//string output = "Player ID\n";
		string output = "";

		foreach (PlayerInfo pi in players)
		{
			output += pi.user_id + "\n";
		}

		return output;
	}


	public string OutputUsernames()
	{
		//string output = "Username\n";
		string output = "";

		foreach (PlayerInfo pi in players)
		{
			output += pi.username + "\n";
		}

		return output;
	}


	public string OutputScores()
	{
		//string output = "Score\n";
		string output = "";

		foreach (PlayerInfo pi in players)
		{
			output += pi.score + "\n";
		}

		return output;
	}

	/* Display the Output of the request sent through
	 * the request string on the given Text parameter.
	 * (i.e. call MakeRequest with the given HTTP
	 * request, then call OutputInfo and display
	 * that on the given Text element reference)
	 * */
	public IEnumerator DisplayOutput(string request, Text t)
	{
		yield return MakeRequest (request);
		t.text = OutputInfo ();
	}

	public IEnumerator DisplayOutputSeparated(bool titles, string request, Text usernames, Text scores)
	{
		yield return MakeRequest (request);

		usernames.text = OutputUsernames ();
		scores.text = OutputScores ();
	}

	public IEnumerator GrabLeaderboard (string request, Text usernames, Text scores, LeaderboardManager lbm)
	{
		// Comment this to test hardcoded players.
		yield return MakeRequest (request);

		// Uncomment this to test hardcoded players.
		//MakePlayers();

		lbm.setPlayers (players);
		lbm.setInitialBoard (usernames, scores);

		// Uncomment this to test hardcoded players.
		//yield return MakeRequest (request);
	}

	/*
	 * Temporary hardcoded players.
	 * */
	public void MakePlayers()
	{
		for(int i = 0; i < 69; i++)
		{
			PlayerInfo temp = new PlayerInfo ();
			temp.username = "A test!" + (i + 1);
			temp.score = i * 69;
			players.Add (temp);
		}
	}
}

