using UnityEngine;
using System.Collections;

public class GameManager : MonoBehaviour{
    public static GameManager Instance;
    enum GameState { Intro, Play, Score, Final};
    ScreenTouch myTouchDelegate;
    private GameState currentState;
    public Spawner spawner;

    private int slices;
    private int score;
    private int afterScore;
    private LevelConfig levelConfig;
    private int countedFigures;
    private int scoreStep;
    private bool toFinal;
    private float finalStarts;

    void Awake()
    {
        Instance = this;
        spawner = GetComponent<Spawner>();
    }

    void Start () {
        if (LevelData.Instance != null)
        {
            levelConfig = LevelData.Instance.CurrentLevelConfig();
        } else {
            levelConfig = new LevelConfig();
            levelConfig.dots = 3;
            levelConfig.slices = 2;
            levelConfig.figures = 4;
            levelConfig.minimumScore = 0.5f;
            levelConfig.specialMoves = false;
        }
        
        currentState = GameState.Intro;
        InputManager.Instance.SetDetectTouch(true);
        myTouchDelegate = new ScreenTouch(TouchParser);
        InputManager.Instance.AddTouchListener(myTouchDelegate);

        slices = levelConfig.slices;
        score = 0;
        Time.timeScale = 1;
         
    }

    public void IntroDone()
    {
        currentState = GameState.Play;
        CanvasManager.Instance.ShowSlice(slices);
        CanvasManager.Instance.ShowTotalScore(score);
        CanvasManager.Instance.ShowLevel(levelConfig);

        spawner.SpawnDots(levelConfig.dots);
        spawner.SpawnFigures(levelConfig.figures);
        Cursor.Instance.SetSpecialMoves(levelConfig.specialMoves);
    }

    private void TouchParser(Vector2 point, TouchState state)
    {
        if (currentState != GameState.Play)
        {
            return;
        }

        Vector2 worldPoint = Camera.main.ScreenToWorldPoint(point);

        if (state == TouchState.Start)
        {
            Cursor.Instance.Begin(worldPoint);
        }

        if (state == TouchState.Stay)
        {
            Cursor.Instance.Drag(worldPoint);
        }

        if (state == TouchState.End)
        {
            Cursor.Instance.End(worldPoint);
        }
    }

    private void ToScore()
    {
        afterScore = 0;
        scoreStep = 0;
        countedFigures = 0;
        currentState = GameState.Score;
        CanvasManager.Instance.ShowResults();

        Figure.Figures.Sort(delegate (Figure a, Figure b)
        {
            return a.damage.CompareTo(b.damage);
        });

        for (int i = 0; i < Figure.Figures.Count; i++)
        {
            Figure.Figures[i].transform.localScale = Vector3.one * 0.5f;
        }
    }

    void Update()
    {
        if (toFinal && (Time.time > finalStarts))
        {
            toFinal = false;
            ShowFinal();
        }

        if (currentState != GameState.Score)
            return;

        Time.timeScale = Mathf.Lerp(Time.timeScale, 1, 0.1f);
        int leap = 12;

        scoreStep += Mathf.FloorToInt(Mathf.Log(Figure.Figures.Count - countedFigures + 5));

        for (int i = 0; i < countedFigures; i++)
        {
            float tmp = (float)i / Figure.Figures.Count;
            tmp = (3 - tmp * tmp * 2);
            float mag = Figure.Figures[i].transform.localScale.x;
            if ((i == countedFigures - 1) && (countedFigures != Figure.Figures.Count))
            {
                Figure.Figures[i].transform.localScale = Vector3.one * mag * 0.98f;
                continue;
            }
            Figure.Figures[i].transform.localScale = Vector3.one * (mag * 0.99f + tmp * 0.01f);
        }

        if ((scoreStep > leap * countedFigures) && (countedFigures < Figure.Figures.Count))
        {
            afterScore += Figure.Figures[countedFigures].damage;
            CanvasManager.Instance.ShowOneScore(Figure.Figures[countedFigures].damage);
            CanvasManager.Instance.ShowTotalScore(afterScore);

            Figure.Figures[countedFigures].GetComponent<Rigidbody2D>().velocity = Vector3.zero;
            Figure.Figures[countedFigures].GetComponent<Rigidbody2D>().angularVelocity *= 0.1f;
            Figure.Figures[countedFigures].GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.FreezePosition;
            Figure.Figures[countedFigures].GetComponent<Rigidbody2D>().gravityScale = 0;
            Figure.Figures[countedFigures].transform.localScale = Vector3.one * 1.2f;
            Figure.Figures[countedFigures].transform.localPosition = new Vector3(0, 0, (Figure.Figures.Count - countedFigures) * 0.1f);

            countedFigures++;

            if (countedFigures == Figure.Figures.Count)
            {
                CanvasManager.Instance.ShowMinimum();
                CanvasManager.Instance.Win(afterScore > levelConfig.MinScore());
                if (afterScore > levelConfig.MinScore())
                {
                    Walls.Instance.Expand();
                    toFinal = true;
                    finalStarts = Time.time + 2;
                }
            }
        }
    }

    private void ShowFinal()
    {
        currentState = GameState.Final;
        foreach (Figure figure in Figure.Figures)
        {
            GameObject.Destroy(figure.gameObject);
        }
        spawner.SpawnFinalDots(levelConfig.figures * 4);
    }

    public void AddScore(int score)
    {
        this.score += score;
        CanvasManager.Instance.ShowTotalScore(this.score);
    }

    public void Slice()
    {
        slices--;
        CanvasManager.Instance.ShowSlice(slices);
        if (slices == 0)
        {
            ToScore();
            return;
        }
    }

    void OnDestroy()
    {
        if (InputManager.Instance != null)
        {
            InputManager.Instance.RemoveTouchListener(myTouchDelegate);
        }
    }

    public void Restart()
    {
        Cursor.Instance.Reset();
        currentState = GameState.Intro;
        spawner.Clear();
        Walls.Instance.Restart();
        slices = levelConfig.slices;
        score = 0;
        Time.timeScale = 1;
    }
}
