using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using System.Linq;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using TMPro;
using UnityEditor;


[System.Serializable]
public class TrackManagerScript : MonoBehaviourPunCallbacks
{    
    [Header("Racetrack Options")]
    [SerializeField] [Range(1, 5)] int m_laps = 3;
    public int LapsInRace { get { return m_laps; } }
    [SerializeField] Color m_trackPrimaryColor = new Color(0.3216002f, 0.5819195f, 0.9339623f);
    [SerializeField] Color m_trackSecondaryColor = new Color(0.1603774f, 0.136926f, 0.136926f);
    [BoolToButton("", "")] [SerializeField] bool m_uiSpace1;
    [BoolToButton("m_setAllTrackColors", "Set Track Colors")]
    [SerializeField] bool m_setAllTrackColors = false;
    [BoolToButton("", "")] [SerializeField] bool m_uiSpace2;

    [Header("Defaults")]
    public Transform trackStart;
    public Transform racerSpots;
	[ReadOnly]
	public Texture sampleFile;
    
    //[ReadOnly]
    public List<SceneField> excludedScenes = new List<SceneField>();
	[ReadOnly]
	public static List<string> trackNames;
	[ReadOnly]
	public bool loadSceneCalled = false, guiActive = false;
	[ReadOnly]
	public Vector2 scrollSpot;
	[ReadOnly]
	public GUISkin sampleSkin;
	[ReadOnly]
	public GUIContent[] playableTracks;
	[ReadOnly]
	public Vote leadingVote;
	[ReadOnly]
	public Vote[] trackVotes;
	[ReadOnly]
	public int selectGridInt = 0, gridSpots = 4;
	[ReadOnly]
	public string selectedLevel = "";

	[ReadOnly]
	public CanvasManagerScript canvasManager;

    [Header("Debug")]
    [SerializeField] DebugChannelSO m_debugChannel;

    private void OnValidate()
    {
        if (m_setAllTrackColors)
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, "Setting track colors");

            foreach (ModularTrack _track in FindObjectsOfType<ModularTrack>())
            {
                ColorChanger _cc = GetComponent<ColorChanger>();

                if (_cc && _cc.objectColors.Length >= 2)
                {
                    _cc.objectColors[0] = m_trackPrimaryColor;
                    _cc.objectColors[1] = m_trackSecondaryColor;
                    _cc.ConvertMaterials();
                }

                foreach (ColorChanger _colorChanger in _track.GetComponentsInChildren<ColorChanger>())
                    if (_colorChanger && _colorChanger.objectColors.Length >= 2)
                    {
                        _colorChanger.objectColors[0] = m_trackPrimaryColor;
                        _colorChanger.objectColors[1] = m_trackSecondaryColor;
                        _colorChanger.ConvertMaterials();
                    }
            }

            AdaptiveTrack _at = FindObjectOfType<AdaptiveTrack>();

            if (_at)
            {
                ColorChanger _cc = _at.GetComponent<ColorChanger>();

                if (_cc && _cc.objectColors.Length >= 2)
                {
                    _cc.objectColors[0] = m_trackPrimaryColor;
                    _cc.objectColors[1] = m_trackSecondaryColor;
                    _cc.ConvertMaterials();
                }
            }

            m_setAllTrackColors = false;
        }
    }

    void Start () {
        if (SceneManager.GetActiveScene().name.Contains("Custom Racer Creator")) { return; }

		if (!trackStart) {
			trackStart = GameObject.FindGameObjectWithTag ("StartFinish").transform;
		}
		if (!racerSpots) {
			racerSpots = GameObject.Find ("Racer Spots").transform;
		}
		if (!sampleFile) {
			sampleFile = Resources.Load<Texture> ("Button Images/RKR Icon");
		}
		if (!sampleSkin) {
			sampleSkin = Resources.Load<GUISkin> ("Button Images/TrackSelectSkin");
		}
		if (!canvasManager)
		{
			canvasManager = GetComponentInChildren<CanvasManagerScript>();
		}
		selectGridInt = -1;

		GetTrackScenes ();

		Vector3 adjustedPos = new Vector3 (trackStart.position.x, trackStart.position.y + 1.13f, trackStart.position.z - 2f);
		if (racerSpots && SceneManager.GetActiveScene().name != "RKR - Esports Lobby") {
			if (PhotonNetwork.IsConnected) {
				bool joinAsSpectator = false;
				object prop;
				if (PhotonNetwork.LocalPlayer.CustomProperties.TryGetValue("IsSpectator", out prop))
				{
					joinAsSpectator = (bool)prop;
					canvasManager.RaceOrSpectateCanvas(joinAsSpectator);
					if (joinAsSpectator)
					{
						Debug.Log(PhotonNetwork.LocalPlayer.ActorNumber - 1 + " - Player is Specator");

						SpectatorController spectatorController = FindObjectOfType<SpectatorController>();
						spectatorController.SpectateAnyPlayer();
					}
					else
					{
						
						//Debug.Log(PhotonNetwork.LocalPlayer.ActorNumber - 1);
						GameObject newPlayer = PhotonNetwork.Instantiate("New Racer", racerSpots.GetChild(PhotonNetwork.LocalPlayer.ActorNumber - 1).position, trackStart.rotation);
					}
				}

			} else {
				Instantiate (Resources.Load("New Racer"), racerSpots.GetChild (0).position, trackStart.rotation);
			}
		}

		/*
		if (SceneManager.GetActiveScene ().name != "PhotonTesting 1" && SceneManager.GetActiveScene ().name != "RKR-Lobby" && SceneManager.GetActiveScene().name != "Esports-Lobby") {
			guiActive = false;
		} else { 
			guiActive = true;
		}
		*/
	}

	public void GetTrackScenes ()
    {
        Debug.Log("Getting scenes...");

        // Create a new list to hold track names
		trackNames = new List<string> ();

        // For each scene in our build settings starting at 2 (0 and 1 are lobby/customizer scenes)
		for (int i = 2; i < SceneManager.sceneCountInBuildSettings; i++)
        {
            // Assume we are not excluding the track
            bool excluded = false;

            // Check each excluded scene name
            foreach (string track in excludedScenes)
                // If there is a match in the given scene...
                if (SceneUtility.GetScenePathByBuildIndex(i).Contains(track))
                {
                    // Exclude the scene
                    excluded = true;

                    Debug.Log("Scene excluded because the name contains " + track + "!");

                    break;
                }

            // If this scene is excluded, continue to the next scene
            if (excluded) { continue; }

            // Otherwise, add this scene to the track list and remove its path info and file name
			trackNames.Add (SceneUtility.GetScenePathByBuildIndex (i).Replace ("Assets/Racetrack Scenes/", "").Replace ("Demo Tracks/(Demo)", "").Replace (".unity", ""));
		}

        // If we didn't get any tracks, return
        if (trackNames.Count < 1)
            return;

        // Create a new array of GUIContent that matches the number of tracks
		playableTracks = new GUIContent[trackNames.Count];

        // Create a new vote array of the same size
		trackVotes = new Vote[trackNames.Count];

        // For each track in the list of names...
		for (int t = 0; t < trackNames.Count; t++)
        {
            // Populate the vote array with a new vote associated with that name
			trackVotes [t] = new Vote (trackNames [t], 0);

            // Do the same for the GUIcontent
			playableTracks [t] = new GUIContent (trackNames [t], sampleFile);
		}

        // By default,, the leading vote and selected level will be the first available level
		leadingVote = trackVotes [0];
		selectedLevel = trackVotes [0].name;

        Debug.Log("Found " + trackNames.Count + " levels. First level is " + selectedLevel);
	}

	public static bool FindTracks () {
		Debug.Log ("Scene Count Build Settings: " + SceneManager.sceneCountInBuildSettings);

		for (int i = 2; i < SceneManager.sceneCountInBuildSettings; i++)
        {
			Debug.LogError (SceneUtility.GetScenePathByBuildIndex (i).Replace ("Assets/Racetrack Scenes/", "").Replace (".unity", ""));
		}

		return true;
		/*
		string[] tempNames = Directory.GetFiles (Application.dataPath + "/Racetrack Scenes");
		trackNames = new List<string> ();

		if (tempNames.Length < 1) {
			Debug.Log ("None");
			return false;
		}
		foreach (string track in tempNames) {
			if (!track.Contains (".meta")) {
				#if UNITY_EDITOR_WIN
				string trackName = track.Substring(track.LastIndexOf('\\') + 1);
				#else
				string trackName = track.Substring(track.LastIndexOf('/') + 1);
				#endif
				trackNames.Add (trackName.Replace (".unity", ""));
			}
		}

		return true;
		*/
	}

	// Update is called once per frame
	void OnGUI () {
		if (!guiActive) {
			return;
		}
        if (SceneManager.GetActiveScene().name.Contains("Custom Racer Creator")) { return; }

        Rect innerBorder = new Rect (Screen.width / 16f, Screen.height / 16f, Screen.width * (7f / 8f), Screen.height * (7f / 8f));
		Rect outerBorder = new Rect (Screen.width / 32f, Screen.height / 32f, Screen.width * (15f / 16f), Screen.height * (15f / 16f));
		
		GUILayout.BeginArea (outerBorder);

		scrollSpot = GUILayout.BeginScrollView (scrollSpot);

		GUILayout.BeginHorizontal ();
		GUILayout.FlexibleSpace ();
		GUILayout.BeginVertical ();
		GUILayout.FlexibleSpace ();

		if (selectGridInt == -1) {
			selectGridInt = GUILayout.SelectionGrid (selectGridInt, playableTracks, gridSpots, sampleSkin.button, GUILayout.MaxWidth(innerBorder.width));
		} else {
			GUILayout.SelectionGrid (selectGridInt, playableTracks, gridSpots, sampleSkin.customStyles[3], GUILayout.MaxWidth(innerBorder.width));
			if (PhotonNetwork.IsConnected) {
				photonView.RPC ("CastVote", RpcTarget.AllBuffered, selectGridInt);
			} else {
				SceneManager.LoadScene (trackNames [selectGridInt]);
			}
			guiActive = false;
		}

		GUILayout.FlexibleSpace ();
		GUILayout.EndVertical ();
		GUILayout.FlexibleSpace ();
		GUILayout.EndHorizontal ();


		GUILayout.EndScrollView ();
		GUILayout.EndArea ();
	}

	IEnumerator LoadRacetrack (int trackNum) {
		if (loadSceneCalled) {
			yield break;
		}
		loadSceneCalled = true;
		yield return new WaitForSecondsRealtime (2f);
		SceneManager.LoadScene (trackNames [trackNum]);
	}

	public void Update () {
		if (Input.GetKeyDown (KeyCode.Semicolon)) {
			bool test = FindTracks ();
			Debug.Log ("End");
			return;
			/*
			if (test) {
				SceneManager.LoadScene (trackNames [1]);
			}
			*/
		}
	}
		

	[PunRPC]	
	public void CastVote (int trackSceneNum) {
		trackVotes [trackSceneNum].AddVote (1);
		//Debug.Log (trackVotes [trackSceneNum].tally);

		for (int i = 0; i < trackVotes.Length; i++) {
			if (leadingVote.tally < trackVotes [i].tally) {
				leadingVote = trackVotes [i];
			}
		}
		selectedLevel = leadingVote.name;
		Debug.Log (selectedLevel);
	}
}

[System.Serializable]
public class TrackQuadrant {
	public ModularTrack start, turn, end;
}

[System.Serializable]
public class Vote {
	public string name;
	public int tally;

	public Vote (string voteName, int voteTally) {
		name = voteName;
		tally = voteTally;
	}

	public void AddVote (int value) {
		tally += value;
	}
}
