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

public class Npc : MonoBehaviour
{
	private bool _playerInit = false;
    private string _name;
    private string _bio;
    private Booth[] _path;
    private Vector3[] _locInNode;
	private Sprite _image;
    public bool[] Infected;
    public float infectionChance = 0.25F;
    // Down to kiss
    public bool[] DTK;
    protected int kissPeriod;
    private static System.Random rand = new System.Random();
    public static int currTime;
    private bool _isFlagged = false;
    private Animator _animator;
    public bool isMoveing = false;

	// Use this for initialization
	void Start ()
    {
        _animator = gameObject.GetComponent<Animator>();
        _animator.Play("Idle");
        gameObject.tag = "Npc";
        kissPeriod = rand.Next(1, 5);
	}

    public void InitNpc(string Name, string Bio, bool IsInfected, int PathLength, Booth EnterPoint, Sprite bioImage)
    {
        _name = Name;
        _bio = Bio;
        _path = new Booth[PathLength];
        _locInNode = new Vector3[PathLength];
		_image = bioImage;
        kissPeriod = rand.Next(1, 5);
        infectionChance = Random.Range(0, 0.5F);

		Infected = new bool[PathLength];

        if (IsInfected)
        {
            Contract(true);
        }

        DTK = new bool[PathLength];

        GeneratePath(EnterPoint);
        GenerateKisstrualCycle();

        _playerInit = true;
    }

	public string Bio { get { return _bio; } }

	public Sprite Image { get { return _image; } }

	public string Name { get { return _name; } }

    public Transform CurrentPosi { get { return gameObject.transform; } }

	public bool CurrentlyInfected { get { return Infected[currTime]; } }

    public bool Flag { get { return _isFlagged; } set { _isFlagged = value; } }

    private void GeneratePath(Booth Start)
    {
        for (int iii = 0; iii < _path.Length; iii++)
        {
            if (iii == 0)
            {
                _path[iii] = Start;
            }
            else
            {
                int destination = rand.Next(0, _path[iii - 1].adjacentBooths.Length);
                _path[iii] = _path[iii - 1].adjacentBooths[destination];
            }

            // TEMP: Needs to get node list from booth!
            _locInNode[iii] = _path[iii].transform.position + new Vector3(Random.Range(-5, 5), 1.5f, Random.Range(-5, 5));
        }
    }

    private void GenerateKisstrualCycle()
    {
        for (int iii = 0; iii < DTK.Length; iii++)
        {
            if (iii % kissPeriod == 0)
            {
                DTK[iii] = true;
            }
            else
            {
                DTK[iii] = false;
            }
        }
    }

    public void StepForward()
    {
        // Play walk animation forwards.
        _path[currTime].npcs.Add(this);
        Move();
    }

    public void StepBack()
    {
        // Play walk animation backwards.
        _path[currTime].npcs.Add(this);
        Move();

        // People don't stay down-to-kiss if they move back in time.
        if (currTime % kissPeriod == 0 && DTK[currTime])
        {
            DTK[currTime] = false;
        }
    }

    public void Idle()
    {
        _animator.Play("Idle");
    }

    public void Move()
    {
        //gameObject.transform.position = gameObject.transform.position + moveVector;
        //gameObject.transform.position = _path[currTime].transform.position + moveVector;
        StartCoroutine(phsyicalMovement(_locInNode[currTime], true));
    }

    private void Kiss(Npc target)
    {
        transform.rotation = Quaternion.identity;
        _animator.Play("Kiss");
        target.ReceiveKiss(this);

        if (Infected[currTime])
        {
            target.Contract(false);
        }

        // Kissing desire has been sated.
        DTK[currTime] = false;
    }

    public void ReceiveKiss(Npc sender)
    {
        transform.rotation = Quaternion.identity;
        transform.position = sender.transform.position + new Vector3(1.25f, 0f);

        sender.transform.Rotate(Vector3.up, 180);

        _animator.Play("Kiss");

        if (Infected[currTime])
        {
            sender.Contract(false);
        }

        // Kissing desire has been sated.
        DTK[currTime] = false;
    }
    
    // Once people contract the disease, they have it for the rest of the game.
    public void Contract(bool guaranteed)
    {
        if (Random.Range(0f,1f) < infectionChance || guaranteed)
        {
            for (int iii = currTime; iii < Infected.Length; iii++)
            {
                Infected[iii] = true;
            }

        }
    }

    public void ReceiveVaccine()
    {
        for (int iii = currTime; iii < Infected.Length; iii++)
        {
            Infected[currTime] = false;
        }

        // Once vaccinated, the person can't get re-infected.
        infectionChance = 0.0f;
    }

    // Update is called once per frame
    void Update ()
    {
		if (!_playerInit)
			return;
	}

    IEnumerator phsyicalMovement(Vector3 endPos, bool forward)
    {
        isMoveing = true;

        //store start and end points
        Vector3 startPos = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z);
        int numberOfSteps = 200;

        float startTime = Time.time;
        float journeyLength = Vector3.Distance(startPos, endPos);

        _animator.Play("Walk");

        if (endPos.x <= startPos.x && gameObject.transform.rotation.y == 0)
        {
            gameObject.transform.Rotate(Vector3.up, 180);
        }
        else if (endPos.x > startPos.x && gameObject.transform.rotation.y == 1)
        {
            gameObject.transform.Rotate(Vector3.up, -180);
        }

        for (int i = 0; i < numberOfSteps; i++)
        {
            float increment = (float)i / (float)numberOfSteps;
            gameObject.transform.position = Vector3.Lerp(startPos, endPos, increment);
            yield return new WaitForEndOfFrame();
        }

        gameObject.transform.position = endPos;

        isMoveing = false;
        bool kissed = false;

        foreach (Npc npc in _path[currTime].npcs)
        {
            float distance = Vector3.Distance(_locInNode[currTime], npc._locInNode[currTime]);
            if (_path[currTime] == npc._path[currTime] && npc != this && DTK[currTime])
            {
                Kiss(npc);
                kissed = true;
                break;
            }
        }

        if (!kissed)
        {
            _animator.Play("Idle");
        }
    }
}
