using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Prisma.Main;
using System;
using UnityEngine.SceneManagement;

namespace Prisma
{
    public class GameMngr : MonoBehaviour
    {

        public delegate void OnClick();
        public static event OnClick onRight;
        public static event OnClick onLeft;
        public static event OnClick onUp;
        public static event OnClick onDown;
        public static event OnClick onD;
        public static event OnClick onS;
        public static event OnClick onRunOn;
        public static event OnClick onRunOff;
        public static event OnClick onHid;
        public static event OnClick onNextLvl;
        public static event OnClick onPad;
        public static bool playeract;
        [SerializeField]
        private int walksp = 1;
        [SerializeField]
        private GameObject player;
        [SerializeField]
        private GameObject door;
        [SerializeField]
        private GameObject cam;
        private GameObject[] guardias;
        [SerializeField]
        private GameObject[] security;

        //GUI
        [SerializeField]
        private GameObject mainmenu;

        //Guardians
        private Transform[] target;
        private float[] xpos;
        private Animator[] ganim;
        private SpriteRenderer[] gsprite;
        private bool[] warn;
        private bool[] endwarn;
        public static int rush;
        private int sign;
        private bool[] checking;
        private bool[] attack;
        private float camVel;
        private Vector2 camVel2;
        private float camX;
        private Vector2 camYZ;
        private Vector2 camYZN;
        private bool lvup;
        private int level;
        private bool ready;
        private bool start;
        [SerializeField]
        private AudioClip[] ambient;
        private AudioSource camsource;
        private bool alarm;
        private bool restore;
        [SerializeField]
        private GameObject[] elevator;
        [SerializeField]
        private GameObject[] guardPos;

        void Start()
        {
            restore = false;
            ready = start = false;
            alarm = false;
            playeract = true;
            rush = 1;
            level = 0;
            lvup = false;
            guardias = GameObject.FindGameObjectsWithTag("Enemy");
            camsource = cam.GetComponent<AudioSource>();
            xpos = new float[guardias.Length];
            ganim = new Animator[guardias.Length];
            gsprite = new SpriteRenderer[guardias.Length];
            warn = new bool[guardias.Length];
            endwarn = new bool[guardias.Length];
            checking = new bool[guardias.Length];
            attack = new bool[guardias.Length];
            target = new Transform[guardias.Length];
            LevelUp();
        }

        public void LevelUp()
        {
            GetComponent<Pad>().PadReset();
            level = level + 1;
            switch (level)
            {
                case 1:
                    camYZ = new Vector2(2.25f,-3.2f);                    
                    camsource.Stop();
                    camsource.clip = ambient[0];
                    camsource.Play();
                    break;
                case 2:
                    camYZ = new Vector2(5.35f, -2.5f);
                    camsource.Stop();
                    camsource.clip = ambient[1];
                    camsource.Play();
                    break;
                case 3:
                    camYZ = new Vector2(7.65f, -2.7f);
                    camsource.Stop();
                    camsource.clip = ambient[2];
                    camsource.Play();
                    break;
                case 4:
                    camYZ = new Vector2(11.8f, -4.5f);
                    camsource.Stop();
                    break;
            }
        }

        public void Victory()
        {
            camsource.clip = ambient[3];
            camsource.Play();
        }

        public int RLevel()
        {
            return level;
        }

        void OnGUI()
        {
            if (!Pad.padact)
            {
                if (Input.GetKey(KeyCode.LeftArrow))
                    if (onLeft != null)
                        onLeft();
                if (Input.GetKey(KeyCode.RightArrow))
                    if (onRight != null)
                        onRight();
                if (Input.GetKey(KeyCode.UpArrow))
                    if (onUp != null)
                        onUp();
                if (Input.GetKey(KeyCode.DownArrow))
                    if (onDown != null)
                        onDown();
            }
            else if (Pad.padact)
            {
                if (Input.GetKeyDown(KeyCode.LeftArrow))
                    if (onLeft != null)
                        onLeft();
                if (Input.GetKeyDown(KeyCode.RightArrow))
                    if (onRight != null)
                        onRight();
                if (Input.GetKeyDown(KeyCode.UpArrow))
                    if (onUp != null)
                        onUp();
                if (Input.GetKeyDown(KeyCode.DownArrow))
                    if (onDown != null)
                        onDown();
            }
            if (Input.GetKeyDown(KeyCode.D))
                if (onD != null)
                    onD();
            if (Input.GetKeyDown(KeyCode.S))
                if (onS != null)
                    onS();
            if (Input.GetKeyDown(KeyCode.W))
                if (onRunOn != null)
                    onRunOn();
            if (Input.GetKeyUp(KeyCode.W))
                if (onRunOff != null)
                    onRunOff();
            if (Input.GetKeyDown(KeyCode.E))
            {
                if (!ready)
                {
                    ready = true;
                    mainmenu.GetComponent<Animator>().SetTrigger("Ready");
                }
                if (ready && !start)
                    start = true;
            }
        }

        public void Alarm()
        {
            StartCoroutine(AlarmTime());
        }

        private IEnumerator AlarmTime()
        {
            alarm = true;
            yield return new WaitForSeconds(5);
            alarm = false;
        }

        private void Update()
        {
            if (!player.GetComponent<Player>().RGGP())
            {
                if (ready && start)
                {
                    if (Vector2.Distance(new Vector2(player.transform.position.x, 0), new Vector2(cam.transform.position.x, 0)) > 1.0f)
                    {
                        camX = Mathf.SmoothDamp(cam.transform.position.x, player.transform.position.x, ref camVel, 1.0f, Mathf.Infinity, Time.deltaTime);
                    }
                    if (Vector2.Distance(new Vector2(camYZ.x, 0), new Vector2(cam.transform.position.y, 0)) > 0.01f && Vector2.Distance(new Vector2(camYZ.y, 0), new Vector2(cam.transform.position.z, 0)) > 0.01f)
                    {
                        camYZN = Vector2.SmoothDamp(new Vector2(cam.transform.position.y, cam.transform.position.z), camYZ, ref camVel2, 1.0f, Mathf.Infinity, Time.deltaTime);
                    }
                    cam.transform.position = new Vector3(camX, camYZN.x, camYZN.y);
                    if (!restore)
                    {
                        for (int i = 0; i < guardias.Length; i++)
                        {
                            warn[i] = guardias[i].GetComponent<GuardiaSc>().Warn();
                            endwarn[i] = guardias[i].GetComponent<GuardiaSc>().REndWarn();
                            checking[i] = guardias[i].GetComponent<GuardiaSc>().RCheck();
                            attack[i] = guardias[i].GetComponent<GuardiaSc>().RAttack();
                            xpos[i] = (float)System.Math.Round(guardias[i].transform.position.x, 2);
                            ganim[i] = guardias[i].GetComponent<Animator>();
                            gsprite[i] = guardias[i].GetComponent<SpriteRenderer>();
                            if (!attack[i])
                            {
                                if (!endwarn[i])
                                {
                                    rush = 1;
                                    target[i] = guardias[i].GetComponent<GuardiaSc>().Target();
                                }
                                else
                                {
                                    rush = 2;
                                    target[i] = player.transform;
                                }
                                if (alarm)
                                    rush = 2;
                                if (target[i].position.x - guardias[i].transform.position.x < 0 && !guardias[i].GetComponent<GuardiaSc>().RCheck())
                                {
                                    sign = 1;
                                    gsprite[i].flipX = false;
                                }
                                else if (target[i].position.x - guardias[i].transform.position.x > 0 && !guardias[i].GetComponent<GuardiaSc>().RCheck())
                                {
                                    sign = -1;
                                    gsprite[i].flipX = true;
                                }
                                if (!guardias[i].GetComponent<GuardiaSc>().RCheck())
                                {
                                    if (sign * Vector2.Distance(new Vector2(guardias[i].transform.position.x, 0), new Vector2(target[i].position.x, 0)) > 0 && !warn[i] && playeract)
                                    {
                                        guardias[i].transform.position = new Vector2(guardias[i].transform.position.x - walksp * rush * Time.deltaTime, guardias[i].transform.position.y);
                                        ganim[i].SetBool("Walking", true);
                                    }
                                    else if (sign * Vector2.Distance(new Vector2(guardias[i].transform.position.x, 0), new Vector2(target[i].position.x, 0)) < 0 && !warn[i] && playeract)
                                    {
                                        guardias[i].transform.position = new Vector2(guardias[i].transform.position.x + walksp * rush * Time.deltaTime, guardias[i].transform.position.y);
                                        ganim[i].SetBool("Walking", true);
                                    }
                                }
                                if (Vector2.Distance(new Vector2(guardias[i].transform.position.x, 0), new Vector2(target[i].position.x, 0)) < 0.1f && target[i].gameObject.name != "Thief") //
                                {
                                    guardias[i].GetComponent<GuardiaSc>().ChangeTarget();
                                }
                                if (Vector2.Distance(new Vector2(guardias[i].transform.position.x, 0), new Vector2(target[i].position.x, 0)) < 0.15f && target[i].gameObject.name == "Thief" && !checking[i])
                                {
                                    guardias[i].GetComponent<GuardiaSc>().Reach();
                                }
                                if (warn[i])
                                    ganim[i].SetBool("Walking", false);
                                if (Input.GetKeyDown(KeyCode.E))
                                {
                                    if (player.GetComponent<Player>().RHidOK())
                                        if (onHid != null)
                                            onHid();
                                    if (player.GetComponent<Player>().RPanel())
                                    {
                                        if (onPad != null)
                                            onPad();
                                    }
                                }
                            }
                            else
                            {
                                ganim[i].SetBool("Walking", false);
                                ganim[i].SetBool("Attack", true);
                                if (Input.GetKeyDown(KeyCode.E))
                                {
                                    StartCoroutine(Restore());
                                }
                            }
                        }
                    }
                }
            }
        }    
        private IEnumerator Restore()
        {
            restore = true;            
            player.GetComponent<Player>().Revive();
            ready = start = true;
            level = 0;
            elevator[0].GetComponent<Animator>().SetTrigger("Reset");
            elevator[1].GetComponent<Animator>().SetTrigger("Reset");
            guardias[0].GetComponent<GuardiaSc>().RestorePos();
            guardias[1].GetComponent<GuardiaSc>().RestorePos();
            guardias[2].GetComponent<GuardiaSc>().RestorePos();
            LevelUp();
            yield return new WaitForSeconds(0.2f);
            player.transform.position = new Vector3(-3.2f, 1, 0);
            playeract = true;
            rush = 1;
            alarm = false;
            for (int j = 0; j < 3; j++)
            {
                guardias[j].GetComponent<GuardiaSc>().ResG();
            }
            yield return new WaitForSeconds(4.8f);
            restore = false;
        }
    }
}