using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;

using PhotonHashTable = ExitGames.Client.Photon.Hashtable;


public class StartMatch : MonoBehaviour {

    // these prefabs are only used if the player isn't connected to photon
    // (so these are only used in the unity editor)
    public GameObject playerPrefab;

    public GameObject llamaPrefab;

    public GameObject[] wandPrefabs;
    public GameObject chestPrefab;

    MapScript mapScript;

    public int minWands = 100;
    public int maxWands = 150;

    public bool spawningPlayer;

    public GameObject StaticLoadingScreen;

    void Awake() {
        StaticLoadingScreen.SetActive(true);
    }

    // Use this for initialization
    void Start () {
        StartCoroutine(FinishLoadingThenStart());
    }

    IEnumerator FinishLoadingThenStart() {
        if (!PhotonNetwork.IsConnected) {
            while (GridHandler.initializing) {
                yield return null;
            }
        }
        else {
            bool completed = false;
            while (!completed) {
                if(!PhotonNetwork.IsConnected || PhotonNetwork.CurrentRoom == null) {
                    yield break;
                }
                Dictionary<int, Photon.Realtime.Player> players = PhotonNetwork.CurrentRoom.Players;
                if (players.Count > 1) {
                    completed = true;
                    foreach (KeyValuePair<int, Photon.Realtime.Player> player in players) {
                        PhotonHashTable playerTable = player.Value.CustomProperties;
                        object prop;
                        if (playerTable.TryGetValue("loading", out prop)) {
                            if ((bool)prop) {
                                completed = false;
                                yield return null;
                                break;
                            }
                        }
                    }
                }
                else
                    yield return null;
            }
        }
        StaticLoadingScreen.SetActive(false);
        mapScript = GameObject.FindGameObjectWithTag("Map Cam").GetComponent<MapScript>();
        mapScript.OpenMapForPlayerToChooseLocationForDrop();
        StartCoroutine(SpawnPlayers());
    }

    IEnumerator SpawnPlayers() {
        spawningPlayer = true;
        yield return new WaitForSecondsRealtime(20f);

        // need to wait to recieve the random seed before spawning anything
        GameGenerator.SetRandomToOldSeed();
        SpawnLlama();

        Random.InitState(System.DateTime.Now.Millisecond + (int)(Time.unscaledTime * 1000));
        if (!mapScript.HasPinBeenPlaced()) {
            SpawnLocalPlayerRandomly();
        }
        else {
            SpawnLocalPlayer(mapScript.GetWorldPositionOfPin());
        }
        GameGenerator.SetRandomToOldSeed();

        mapScript.CloseMapForPlayerToChooseLocationForDrop();
        spawningPlayer = false;
    }

    void SpawnLlama() {
        Vector3 spawnPoint = GetRandomSpawnPoint();
        spawnPoint.y += 4f;
        if (llamaPrefab)
            Instantiate(llamaPrefab, spawnPoint, Quaternion.identity);
    }

    void SpawnLocalPlayer(Vector3 spawnPoint) {
        spawnPoint.y += 150f;
        if (PhotonNetwork.IsConnected) {
            PhotonNetwork.Instantiate("player", spawnPoint, Quaternion.identity);
        }
        else {
            Instantiate(playerPrefab, spawnPoint, Quaternion.identity);
        }
    }

    void SpawnLocalPlayerRandomly() {
        SpawnLocalPlayer(GetRandomSpawnPoint());
    }

    void SpawnLocalPlayerAtPosition(Vector2 mapPoint) {
        SpawnLocalPlayer(GetSpawnPointFromMapPoint(mapPoint));
    }

    Vector3 GetRandomSpawnPoint() {
        Vector3 point = new Vector3(Random.Range(-500, 500), 300f, Random.Range(-500, 500));
        Ray ray = new Ray(point, Vector3.down);
        RaycastHit hit = new RaycastHit();
        if (Physics.Raycast(ray, out hit)) {
            point.y = hit.point.y;
        }
        return point;
    }

    Vector3 GetSpawnPointFromMapPoint(Vector2 mapPoint) {
        return mapPoint;
    }
}
