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

public class Slicer : MonoBehaviour {
    public static Slicer Instance;

    public struct Cut
    {
        public Transform trans;
        public Vector2 pointR;
        public Vector2 pointL;
        public bool super;

        public Vector2 Tangent()
        {
            return new Vector2(pointL.y - pointR.y, pointR.x - pointL.x).normalized;
        }
    }

    private int figureMask;
    private List<Cut> cuts;

    List<Vector3> vertices;
    List<Color> colors;
    List<int> triangles;
    MeshFilter meshFilter;
    private float strength;

    void Awake()
    {
        Instance = this;
    }

    void Start () {
        figureMask = 1 << LayerMask.NameToLayer("FIGURE");

        vertices = new List<Vector3>();
        colors = new List<Color>();
        triangles = new List<int>();
        meshFilter = GetComponent<MeshFilter>();
        cuts = new List<Cut>();
    }

    public void SliceLine(Vector2 diff) {
        strength = 1;
        int dotCount = Dot.Dots.Count;
        cuts.Clear();
        int score = 0;

        for (int i = 0; i < dotCount; i++)
        {
            score += SliceScore(i, diff);
        }

        GameManager.Instance.AddScore(score);
    }

    public void SlicePush(Vector2 point)
    {
        strength = 1;
        int dotCount = Dot.Dots.Count;
        cuts.Clear();
        int score = 0;

        for (int i = 0; i < dotCount; i++)
        {
            Vector2 diff = - ((Vector3)point - Dot.Dots[i].transform.position);
            score += SliceScore(i, diff.normalized * 2);
        }

        GameManager.Instance.AddScore(score);
    }

    public void SlicePull(Vector2 point)
    {
        strength = 1;
        int dotCount = Dot.Dots.Count;
        cuts.Clear();
        int score = 0;

        for (int i = 0; i < dotCount; i++)
        {
            Vector2 diff = ((Vector3)point - Dot.Dots[i].transform.position);
            score += SliceScore(i, diff.normalized * 2);
        }

        GameManager.Instance.AddScore(score);
    }

    private int SliceScore(int dotIndex, Vector2 diff)
    {
        int score = 0;
        int mod = 100;
        if (Dot.Dots[dotIndex].IsFresh())
        {
            mod = 200;
        }

        Vector2 pos = Dot.Dots[dotIndex].transform.position;
        RaycastHit2D[] hitsR = Physics2D.LinecastAll(pos - diff * 1f, pos + diff * 2f, figureMask);
        RaycastHit2D[] hitsL = Physics2D.LinecastAll(pos + diff * 2f, pos - diff * 1f, figureMask);

        for (int j = 0; j < hitsR.Length; j++)
        {
            Cut cut = new Cut();
            cut.trans = hitsR[j].transform;
            cut.pointR = hitsR[j].point;

            for (int k = 0; k < hitsL.Length; k++)
            {
                if (hitsR[j].transform == hitsL[k].transform)
                {
                    cut.pointL = hitsL[k].point;
                    cut.super = false;
                    int tmp = Mathf.FloorToInt((cut.pointR - cut.pointL).magnitude * mod);
                    if ((cut.pointL - cut.pointR).magnitude > 1.9)
                    {
                        tmp *= 2;
                        cut.super = true;
                    }
                    score += tmp;
                    cut.trans.GetComponent<Figure>().AddBrush(cut, cut.super, tmp);
                    cuts.Add(cut);
                }
            }
        }

        Dot.Dots[dotIndex].Impulse(diff);
        return score;
    }

    void Update (){
        if (strength == 0)
        {
            return;
        }
        strength = Mathf.Clamp01(strength - (Time.unscaledDeltaTime + Time.deltaTime * 4));
        if (strength == 0)
        {
            meshFilter.mesh = new Mesh();
            return;
        }

        //GetComponent<MeshRenderer>().material.color = Color.blue;

        vertices.Clear();
        colors.Clear();
        triangles.Clear();
        Mesh sliceMesh = new Mesh();

        Vector2 tan;

        for (int i = 0; i < cuts.Count; i++)
        {
            tan = cuts[i].Tangent() * 0.1f * strength;

            if (cuts[i].super)
            {
                colors.Add(Color.red);
                colors.Add(Color.red);
                colors.Add(Color.red);
                colors.Add(Color.red);

                vertices.Add((Vector3)(cuts[i].pointL + tan) - new Vector3(0, 0, 1));
                vertices.Add((Vector3)(cuts[i].pointR + tan) - new Vector3(0, 0, 1));
                vertices.Add((Vector3)(cuts[i].pointR - tan) - new Vector3(0, 0, 1));
                vertices.Add((Vector3)(cuts[i].pointL - tan) - new Vector3(0, 0, 1));
            }
            else
            {
                colors.Add(Color.blue);
                colors.Add(Color.blue);
                colors.Add(Color.blue);
                colors.Add(Color.blue);

                vertices.Add(cuts[i].pointL + tan);
                vertices.Add(cuts[i].pointR + tan);
                vertices.Add(cuts[i].pointR - tan);
                vertices.Add(cuts[i].pointL - tan);
            }

            triangles.Add(i * 4);
            triangles.Add(i * 4 + 1);
            triangles.Add(i * 4 + 3);

            triangles.Add(i * 4 + 1);
            triangles.Add(i * 4 + 2);
            triangles.Add(i * 4 + 3);
        }

        sliceMesh.vertices = vertices.ToArray();
        sliceMesh.colors = colors.ToArray();
        sliceMesh.triangles = triangles.ToArray();
        sliceMesh.RecalculateNormals();
        
        meshFilter.mesh = sliceMesh;
    }
}
