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

public class PlayerScript : MonoBehaviour {

    // these are first level specific bools
    bool lappupois;
    bool jalka1pois;
    bool jalka2pois;
    bool jalka3pois;
    bool jalka4pois;
    bool ruumispois;
    public Sprite[] robolegs;
    public Sprite roboface;

    public int points;

    public bool flymode;

    public GameObject egg;

    public GameObject lasersprite;
    float laserstarttime;
    GameObject la;

    bool jumping;
    float jumpstart;
    float jumpdir;

    bool inceiling;
    float ceilingstart;

    float lastshoottime;

    // float lastjumptime; // now called jumpstart
    float lastgroundtime;
    Vector2 grounddir;

    bool firstlevel;

    public bool dontReload = false;

    //Vector3 CoM;

    //public GameObject[] legs;

    public List<KeyValuePair<float, KeyValuePair<string, int>>> events;

	// Use this for initialization
	void Awake () {
        if (Progress.LatestDefeat() == null)
            firstlevel = true;
        else
            firstlevel = false;
        //print("sdafds");
        points = 0;
        /*legs = new GameObject[] {
            transform.Find("virus_ruumis/virusjalka1").gameObject,
            transform.Find("virus_ruumis/virusjalka2").gameObject,
            transform.Find("virus_ruumis/virusjalka3").gameObject,
            transform.Find("virus_ruumis/virusjalka4").gameObject
        };*/
        grounddir = Physs.up;
        events = new List<KeyValuePair<float, KeyValuePair<string, int>>>();
	}

    private void Start()
    {
        if (!firstlevel) FullReplace();
        //print("sdf");
        //LayEggs();
        //FullReplace();
    }

    // Update is called once per frame
    void Update () {
        

        float ls = 0.8f;
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            transform.position += Physs.left*ls;
            GetComponent<Rigidbody2D>().velocity = Vector3.zero;
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            transform.position += Physs.right *ls;
            GetComponent<Rigidbody2D>().velocity = Vector3.zero;
        }
        if (Input.GetKey(KeyCode.UpArrow))
        {
            transform.position += Physs.up *ls;
            GetComponent<Rigidbody2D>().velocity = Vector3.zero;
        }
        if (Input.GetKey(KeyCode.DownArrow))
        {
            transform.position += Physs.down * ls;
            GetComponent<Rigidbody2D>().velocity = Vector3.zero;
        }

        //GameObject.Find("arrow").transform.localRotation =
        //    Quaternion.EulerAngles(0, 0, Mathf.Atan2(grounddir.y, grounddir.x) - 90);

        //GameObject.CreatePrimitive(PrimitiveType.Capsule).transform.position = transform.position + (Vector3)grounddir*5 ;

        bool ong = OnGround();
        if (ong && !flymode) JumpingMoving();
        else
        {
            FlyMoving();
            print(0);
            GetComponent<Animator>().SetTrigger("Idle");
        }

        if (Input.GetKey(KeyCode.Q))
        {
            transform.Rotate(new Vector3(0, 0, 3f));
        }
        if (Input.GetKey(KeyCode.E))
        {
            transform.Rotate(new Vector3(0, 0, -3f));
        }
        if (Input.GetKey(KeyCode.S))
        {
            Vector2 d = GroundDir(0);
            if (true) /*d != Vector2.zero && Vector2.Dot(Physs2.down, d) > 0.7f*/
            {
                GetComponent<Rigidbody2D>().AddForce(-d*12); //Physs2.up*10);
                GetComponent<CoolTracker>().Inform("ceiling", 0);
            }
            inceiling = true;
            ceilingstart = Time.time;
        }

        // shooting lasers
        if (Input.GetMouseButtonDown(0))
        {
            if (Time.time - laserstarttime >= 1f)
            {
                if (firstlevel)
                {
                    GameObject.Destroy(GameObject.Find("lappu"));
                }
                laserstarttime = Time.time;
                la = GameObject.Instantiate(lasersprite, Vector3.zero, Quaternion.identity);
                GetComponent<AudioSource>().Play();
                GetComponent<Animator>().SetTrigger("Laser");
                //transform.position + dire,
                //Quaternion.EulerAngles(0, 0, Mathf.Atan2(dire.y, dire.x)));
                //
                //dire = dire + (Vector3)Random.insideUnitCircle * 0.1f;
            }
        }
        if (true || Input.GetMouseButton(0))
        {
            if (la != null)
            {
                float max = 200;
                Vector3 ss = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                Vector3 dire = (ss - transform.position).normalized;
                RaycastHit2D rh2s = Physics2D.Raycast(transform.position, dire, max,
                    ~(LayerMask.GetMask("player") | LayerMask.GetMask("enemy") | (2 << Physics.IgnoreRaycastLayer)));
                la.GetComponent<LineRenderer>().SetPosition(0, transform.position + 3*Vector3.back + 0.65f*transform.up - 0.6f*transform.right);
                if (rh2s.collider != null && rh2s.distance < max)
                    la.GetComponent<LineRenderer>().SetPosition(1, (Vector3)rh2s.point + 3 * Vector3.back);
                else
                    la.GetComponent<LineRenderer>().SetPosition(1, transform.position + dire * max + 3 * Vector3.back);
            }
        }
        if (/*Input.GetMouseButtonUp(0) ||*/ la != null && Time.time - laserstarttime > 0.3f)
        {
            GameObject.Destroy(la);
        }

        if (Input.GetKey(KeyCode.H) && Input.GetKey(KeyCode.O) && Input.GetKey(KeyCode.P))
        {
            dontReload = true;
            Progress.MarkAsDefeated(UnityEngine.SceneManagement.SceneManager.GetActiveScene().name, points);
            UnityEngine.SceneManagement.SceneManager.LoadScene("overworld");
        }
        if (Input.GetKey(KeyCode.H) && Input.GetKey(KeyCode.L) && Input.GetKey(KeyCode.T))
        {
            GetComponent<HealthScript>().orighealth = 1000000;
            GetComponent<HealthScript>().health = 1000000;
        }

    }

    public void IKilled(GameObject enemy)
    {
        //events.Add(new KeyValuePair<float, KeyValuePair<string, int>> (Time.time, new KeyValuePair<string,int>("kill", enemy.GetComponent<PointsGive>().points)));
        GetComponent<CoolTracker>().Inform("kill", enemy.GetComponent<PointsGive>().points);
        points += enemy.GetComponent<PointsGive>().points;
    }

    public void LayEggs()
    {
        for (int i = 0; i < 30; i++)
        {
            GameObject.Instantiate(egg, transform.position - transform.up*1.5f + (Vector3)Random.insideUnitCircle*2, Quaternion.identity);
        }
    }

    void JumpingMoving()
    {
        //sprint(grounddir);
        //if (Time.time - lastjumptime < 0.3f) return;
        //print("heere");
        float dir = 0;
        if (Input.GetKey(KeyCode.D))
        {
            if (!jumping || jumpdir == 0) Move(1); // move right. 
            dir += 1;
        }
        if (Input.GetKey(KeyCode.A))
        {
            if (!jumping || jumpdir == 0) Move(-1);
            dir -= 1;
        }
        if (dir == 0) {
            GetComponent<Animator>().SetTrigger("Idle");
            print(0);
        }
        //jumping here
        if (!flymode && Input.GetKeyDown(KeyCode.W) && !jumping && Time.time - jumpstart > 0.8f && (Time.time - lastgroundtime) < 0.3f )//Input.GetMouseButtonDown(0) && OnGround() )
        {
            jumping = true;
            jumpdir = dir;
            jumpstart = Time.time;
            if (Vector2.Dot(Physs2.left, grounddir) > 0.3f)
            {
                jumpdir = -1;
            }
            else if (Vector2.Dot(Physs2.right, grounddir) > 0.3f)
            {
                jumpdir = 1;
            }
        }
        if(jumping)
        {
            float force = 30;
            if (Time.time - jumpstart > 0.25f) force = 15;
            GetComponent<Rigidbody2D>().AddForce(/*(2 * Physs2.up +
                 jumpdir * Physs2.right).normalized*/ transform.up * force);
        }
        if (Input.GetKeyUp(KeyCode.W) || Time.time - jumpstart > 0.5f)
        {
            jumping = false;
        }

        

        /*if (Time.time - ceilingstart > 0.5f && Input.GetKeyDown(KeyCode.W) && Time.time - jumpstart > 0.3f)
        {
            jumpstart = Time.time;
            GetComponent<Rigidbody2D>().AddForce(Vector2.down * 300);
        }*/

    }

    void FlyMoving()
    {
        if (!flymode)
        {
            if (Input.GetKey(KeyCode.D))
            {
                GetComponent<Rigidbody2D>().AddForce(Physs.right * 4);
            }
            if (Input.GetKey(KeyCode.A))
            {
                GetComponent<Rigidbody2D>().AddForce(Physs.left * 4);
            }
        }
        if (!flymode)
        {
            if (Input.GetKey(KeyCode.D))
            {
                GetComponent<Rigidbody2D>().AddForce(Physs.right * 2);
            }
            if (Input.GetKey(KeyCode.A))
            {
                GetComponent<Rigidbody2D>().AddForce(Physs.left * 2);
            }
        }

        if (flymode && !jumping && Input.GetKey(KeyCode.W))
        {
            //print("here");
            GetComponent<Rigidbody2D>().AddForce(/*(2 * Physs2.up +
                 jumpdir * Physs2.right).normalized*/ transform.up*12);
        }

    }

    private Vector2 GroundDir(float dir)
    {
        if (dir == 0)
        {
            return (GroundDir(-1) + GroundDir(1)).normalized;
        }
        Vector2 gd;
        Vector3 right = transform.right * dir;
        Vector2[] normals = new Vector2[10];

        int c = 0;
        Vector2 normal = Vector2.zero;
        for (int i = 0; i < 10; i++)
        {

            RaycastHit2D rh2d = Physics2D.Raycast(transform.position + right * i * 0.2f, -transform.up, 4f, ~(LayerMask.GetMask(new string[] { "player" }) | (2 << Physics.IgnoreRaycastLayer)));
            if (rh2d.rigidbody != null && rh2d.distance <= 4)
            {
                c++;
                normal += rh2d.normal;
                //GameObject.CreatePrimitive(PrimitiveType.Capsule).transform.position = rh2d.point;
            }
        }
        //print(c);
        if (c != 0)
        {
            gd = (normal / c).normalized;
        }
        else gd = Vector2.zero;
        return gd;
    }

    private void Move(float dir)
    {
        if (dir < 0)
            GetComponent<Animator>().SetTrigger("WalkLeft");
        else
            GetComponent<Animator>().SetTrigger("WalkRight");
        print(dir);
        //if (dir != 1) return;
        // a priori direction
        grounddir = GroundDir(dir);
        float speedmul = 40;
        
        Vector2 togo = dir * new Vector2(grounddir.y, -grounddir.x);
            // it's counterintuitive to go in the opposite direction than pressed
            if (Vector2.Dot(grounddir, Physs.down) > 0.1f)
            {
            //GetComponent<Rigidbody2D>().AddForce(dir * Vector2.right * 10); // faster fly moving here for some reason, 4 otherwise
            dir = dir * -1;
            speedmul = 5; // just because no friction in the ceiling basically
            }
            if (Vector2.Dot(GetComponent<Rigidbody2D>().velocity, togo) < 8)
            {
                GetComponent<Rigidbody2D>().AddForce(dir * new Vector2(grounddir.y, -grounddir.x) * speedmul);
                //print("not max");
            } else
            {
               // print("max!");
            }
    }
    private void OnDestroy()
    {
        if (la != null) Destroy(la);

        // force level re-load on death
        if (dontReload) return;
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }


    private bool OnGround()
    {
        /*foreach (GameObject l in legs)
        {
            if (Time.time - l.GetComponent<CollisionRememberer>().lastcollisiontime < 0.1f)  return true;
        }
        return false;*/
        RaycastHit2D rh2d = Physics2D.Raycast(transform.position, -transform.up, 4.5f, ~(LayerMask.GetMask(new string[] { "player" }) | (2 << Physics.IgnoreRaycastLayer)));

        //print(rh2d.distance != null);
        if (rh2d.rigidbody != null)
        {
            lastgroundtime = Time.time;
            return true;
        }
        return false;
    }

    
    /*
    private void OnGUI()
    {
        GUI.Label(new Rect(0, 0, 300, 60), GetComponent<Animator>().GetInteger("Walk").ToString());
        /*GUI.Label(new Rect(0, 0, 300, 60), jumping.ToString());
        GUI.Label(new Rect(0, 60, 300, 60), GroundDir(0).ToString());
        GUI.Label(new Rect(0, 180, 300, 60), GetComponent<HealthScript>().health.ToString());
        GUI.Label(new Rect(0, 220, 300, 60), OnGround().ToString());
        GUI.Label(new Rect(0, 250, 300, 60), jumping.ToString());*/
   // }
    

    public void OnCollisionStay2D(Collision2D collision)
    {
        //print("es");
        DamageDealer dd = collision.rigidbody.gameObject.GetComponent<DamageDealer>();
        if (dd == null) return;
        GetComponent<HealthScript>().TakeDamage(dd.damage); //.health.take -= dd.damage;
        GetComponent<Animator>().SetTrigger("TakeDamage");

        GetComponent<Rigidbody2D>().AddForce(-150 * (collision.transform.position - transform.position).normalized);
        collision.rigidbody.AddForce(50 * (collision.transform.position - transform.position).normalized);
    }

    
    public void OnCollisionEnter2D(Collision2D collision)
    {
        if (!firstlevel) return; // since only for undressing
        if (collision.relativeVelocity.magnitude > 10)
        {
            
            //bool lappupois;
            //bool jalka1pois;
            //bool jalka2pois;
            //bool jalka3pois;
            //bool jalka4pois;
            //bool ruumispois;
            
            if (!jalka1pois)
            {
                if (Random.Range(0,4) ==0)
                {
                    Insta(GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().sprite, GameObject.Find("virusjalka1").transform.position);
                    GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().sprite = robolegs[0];
                    GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().enabled = false;
                    GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().enabled = true;
                    jalka1pois = true;
                }
            }
            if (!jalka2pois)
            {
                if (Random.Range(0, 4) == 0)
                {
                    Insta(GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().sprite, GameObject.Find("virusjalka2").transform.position);
                    GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().sprite = robolegs[1];
                    GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().enabled = false;
                    GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().enabled = true;
                    jalka2pois = true;
                }
            }
            if (!jalka3pois)
            {
                if (Random.Range(0, 4) == 0)
                {
                    Insta(GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().sprite, GameObject.Find("virusjalka3").transform.position);
                    GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().sprite = robolegs[2];
                    GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().enabled = false;
                    GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().enabled = true;
                    jalka3pois = true;
                }
            }
            if (!jalka4pois)
            {
                if (Random.Range(0, 4) == 0)
                {
                    Insta(GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().sprite, GameObject.Find("virusjalka4").transform.position);
                    GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().sprite = robolegs[3];
                    GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().enabled = false;
                    GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().enabled = true;
                    jalka4pois = true;
                }
            }
            if (!ruumispois && jalka1pois && jalka2pois && jalka3pois && jalka4pois)
            {
                Insta(GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().sprite, GameObject.Find("virus_ruumis").transform.position);
                GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().sprite = roboface;
                GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().enabled = false;
                GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().enabled = true;
                ruumispois = true;
            }
        }
    }

    void FullReplace()
    {
        //print("ss");
        GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().sprite = robolegs[0];
        GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().enabled = false;
        GameObject.Find("virusjalka1").GetComponent<SpriteRenderer>().enabled = true;
        GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().sprite = robolegs[1];
        GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().enabled = false;
        GameObject.Find("virusjalka2").GetComponent<SpriteRenderer>().enabled = true;
        GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().sprite = robolegs[2];
        GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().enabled = false;
        GameObject.Find("virusjalka3").GetComponent<SpriteRenderer>().enabled = true;
        GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().sprite = robolegs[3];
        GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().enabled = false;
        GameObject.Find("virusjalka4").GetComponent<SpriteRenderer>().enabled = true;
        GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().sprite = roboface;
        GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().enabled = false;
        GameObject.Find("virus_ruumis").GetComponent<SpriteRenderer>().enabled = true;
        GameObject.Destroy(GameObject.Find("lappu"));
    }

    public void Insta(Sprite s, Vector3 pos)
    {
        GameObject g = new GameObject();
        g.layer = LayerMask.NameToLayer("player");
        g.AddComponent<Rigidbody2D>().mass = 0.1f;
        g.GetComponent<Rigidbody2D>().angularDrag = 5;
        g.AddComponent<CircleCollider2D>().radius = 0.2f;
        g.AddComponent<SpriteRenderer>().sprite = s;
        g.transform.position = pos;
    }
}
