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


//-0.0812
public struct GameState
{
    public Piece piece;
    public Team team;
    public GameObject refrence;
    public RenderState rs;
    public bool selected;
    public bool animate;
}
public enum RenderState
{
Empty,Moveable,Takeable,Select
}
public enum Team
{
White=0,Black=1
}
public class GameController : MonoBehaviour
{
    public GameObject[] piecesBlack;
    public GameObject[] piecesWhite;
    public AudioClip[] audios;
    public GameObject grid;
    public GameObject Selected;
    List<GameObject> Taken_B = new List<GameObject>(), Taken_W = new List<GameObject>();
    GameObject[,] grids = new GameObject[8, 8];
    AudioSource a;
    public GameState[,] gameState = new GameState[8, 8];
    public Texture TSelect, TMoveable, TTakeable;
    public Material rawMaterial;
    Material MSelect, MMoveable, MTakeable;
    Vector2 lastSelect;
    int lsx, lsy;
    bool escape;
    public Team turn;
    public Team selfTeam;
    public Manager gm;
    public Text UIText;
    bool clicked;
    Mesh queenMesh;
    // Start is called before the first frame update

    public void Initiate()
    {
        foreach (GameObject g in Taken_B)
        {
            Destroy(g);
        }
        foreach (GameObject g in Taken_W)
        {
            Destroy(g);
        }
        Taken_B.Clear();
        Taken_W.Clear();
        for (int x = 0; x < 8; x++)
        {
            for (int y = 0; y < 8; y++)
            {
                if (gameState[x, y].refrence != null) Destroy(gameState[x, y].refrence);
                gameState[x, y].rs = RenderState.Empty;
                gameState[x, y].piece = Piece.Empty;
            }
        }
        for (int i = 0; i < 8; i++)
        {
            gameState[0, i].team = Team.Black;
        }
        for (int i = 0; i < 8; i++)
        {
            gameState[1, i].team = Team.Black;
        }
        for (int i = 0; i < 8; i++)
        {
            gameState[1, i].piece = Piece.Pawn;
            gameState[1, i].refrence = Instantiate(piecesBlack[(int)Piece.Pawn], transform);
        }
        gameState[0, 0].piece = Piece.Tower;
        gameState[0, 0].refrence = Instantiate(piecesBlack[(int)Piece.Tower], transform);

        gameState[0, 7].piece = Piece.Tower;
        gameState[0, 7].refrence = Instantiate(piecesBlack[(int)Piece.Tower], transform);

        gameState[0, 1].piece = Piece.Horse;
        gameState[0, 1].refrence = Instantiate(piecesBlack[(int)Piece.Horse], transform);

        gameState[0, 6].piece = Piece.Horse;
        gameState[0, 6].refrence = Instantiate(piecesBlack[(int)Piece.Horse], transform);

        gameState[0, 2].piece = Piece.Bishop;
        gameState[0, 2].refrence = Instantiate(piecesBlack[(int)Piece.Bishop], transform);

        gameState[0, 5].piece = Piece.Bishop;
        gameState[0, 5].refrence = Instantiate(piecesBlack[(int)Piece.Bishop], transform);

        gameState[0, 3].piece = Piece.Queen;
        gameState[0, 3].refrence = Instantiate(piecesBlack[(int)Piece.Queen], transform);

        gameState[0, 4].piece = Piece.King;
        gameState[0, 4].refrence = Instantiate(piecesBlack[(int)Piece.King], transform);

        //gameState[4, 3].team = Team.Black;

        for (int i = 0; i < 8; i++)
        {
            gameState[7, i].team = Team.White;
        }
        for (int i = 0; i < 8; i++)
        {
            gameState[6, i].team = Team.White;
        }
        for (int i = 0; i < 8; i++)
        {
            gameState[6, i].piece = Piece.Pawn;
            gameState[6, i].refrence = Instantiate(piecesWhite[(int)Piece.Pawn], transform);

        }
        gameState[7, 0].piece = Piece.Tower;
        gameState[7, 0].refrence = Instantiate(piecesWhite[(int)Piece.Tower], transform);

        gameState[7, 7].piece = Piece.Tower;
        gameState[7, 7].refrence = Instantiate(piecesWhite[(int)Piece.Tower], transform);

        gameState[7, 1].piece = Piece.Horse;
        gameState[7, 1].refrence = Instantiate(piecesWhite[(int)Piece.Horse], transform);

        gameState[7, 6].piece = Piece.Horse;
        gameState[7, 6].refrence = Instantiate(piecesWhite[(int)Piece.Horse], transform);

        gameState[7, 2].piece = Piece.Bishop;
        gameState[7, 2].refrence = Instantiate(piecesWhite[(int)Piece.Bishop], transform);

        gameState[7, 5].piece = Piece.Bishop;
        gameState[7, 5].refrence = Instantiate(piecesWhite[(int)Piece.Bishop], transform);

        gameState[7, 3].piece = Piece.Queen;
        gameState[7, 3].refrence = Instantiate(piecesWhite[(int)Piece.Queen], transform);

        gameState[7, 4].piece = Piece.King;
        gameState[7, 4].refrence = Instantiate(piecesWhite[(int)Piece.King], transform);

        UpdatePosition();

    }
    void UpdatePosition(bool onlyrender = false)
    {
        for (int x = 0; x < 8; x++)
        {
            for (int y = 0; y < 8; y++)
            {
                if (gameState[x, y].refrence != null)
                {
                    if (gameState[x, y].animate)
                    {
                        gameState[x, y].refrence.GetComponent<PieceController>().Move(new Vector3(0.4991f - 0.1425f * x, 0, 0.4991f - 0.1425f * y),this);
                        gameState[x, y].animate = false;
                    }
                    else
                    {
                        gameState[x, y].refrence.transform.position = new Vector3(0.4991f - 0.1425f * x, 0, 0.4991f - 0.1425f * y);
                    } 
                }

                if (gameState[x, y].rs == RenderState.Empty)
                {
                    grids[x, y].transform.eulerAngles = new Vector3(-90, 0, 0);
                }
                if (gameState[x, y].rs == RenderState.Moveable)
                {
                    grids[x, y].GetComponent<MeshRenderer>().sharedMaterial = MMoveable;
                    grids[x, y].transform.eulerAngles = new Vector3(90, 0, 0);
                }
                if (gameState[x, y].rs == RenderState.Takeable)
                {
                    grids[x, y].GetComponent<MeshRenderer>().sharedMaterial = MTakeable;
                    grids[x, y].transform.eulerAngles = new Vector3(90, 0, 0);
                }
                if (gameState[x, y].selected)
                {
                    grids[x, y].GetComponent<MeshRenderer>().sharedMaterial = MSelect;
                    grids[x, y].transform.eulerAngles = new Vector3(90, 0, 0);
                }

            }
        }
        if (onlyrender) return;
        for (int i = 0; i < Taken_B.Count; i++)
        {
            if (Taken_B[i].GetComponent<PieceController>().Taken == false)
            { //Taken_B[i].transform.position = new Vector3(0.4991f , 0, 0.4991f - 0.1425f * 7);
                if (i <= 7)
                {
                    Taken_B[i].GetComponent<PieceController>().Move(new Vector3(0.4991f - 0.1425f * i, -0.0812f, 0.4991f - 0.1425f * 7 - 0.22f), this, AudioState.Taken);
                    //Taken_B[i].transform.Translate(0.1425f * i, -0.0812f , -0.22f);
                }
                else
                {
                    Taken_B[i].GetComponent<PieceController>().Move(new Vector3(0.4991f - 0.1425f * (i - 8), -0.0812f, 0.4991f - 0.1425f * 7 - 0.22f - 0.1425f), this, AudioState.Taken);
                    //Taken_B[i].transform.Translate(0.1425f * (i-8), -0.0812f , -0.22f-0.1425f);
                }
            }
            Taken_B[i].GetComponent<PieceController>().Taken = true;
        }
        for (int i = 0; i < Taken_W.Count; i++)
        {
            if (Taken_W[i].GetComponent<PieceController>().Taken == false)
            {
                //Taken_W[i].transform.position = new Vector3(0.4991f - 0.1425f * 7, 0, 0.4991f);
                if (i <= 7)
                {
                    Taken_W[i].GetComponent<PieceController>().Move(new Vector3(0.4991f - 0.1425f * 7 + 0.1425f * i, -0.0812f, 0.4991f + 0.22f), this, AudioState.Taken);
                    //Taken_W[i].transform.Translate(-0.1425f * i, -0.0812f, 0.22f);
                }
                else
                {
                    Taken_W[i].GetComponent<PieceController>().Move(new Vector3(0.4991f - 0.1425f * 7 + 0.1425f * (i - 8), -0.0812f, 0.4991f + 0.22f + 0.1425f), this, AudioState.Taken);
                    //Taken_W[i].transform.Translate(-0.1425f * (i - 8), -0.0812f, 0.22f + 0.1425f);
                }
                Taken_W[i].GetComponent<PieceController>().Taken = true;
            }
        }

    }
    void SelectGrid(int x, int y)
    {
        if (gameState[x, y].team == selfTeam || gameState[x, y].rs != RenderState.Empty)
        {
            if (gameState[x, y].rs != RenderState.Empty && !gameState[x, y].selected)
            {
                gm.SendMove(lsx, lsy, x, y);
                //Move(lsx,lsy,x,y);
            }
            else
            {
                ClearState();
                gameState[(int)lastSelect.x, (int)lastSelect.y].selected = false;
                if (gameState[x, y].piece != Piece.Empty)
                    gameState[x, y].selected = true;
                lastSelect = new Vector2(x, y);
                if (gameState[x, y].piece != Piece.Empty)
                {
                    lsx = x; lsy = y;
                }
                if (gameState[x, y].team == Team.Black)
                {
                    if (gameState[x, y].piece == Piece.Pawn) SelectPawn_B(x, y);
                }
                if (gameState[x, y].team == Team.White)
                {
                    if (gameState[x, y].piece == Piece.Pawn) SelectPawn_W(x, y);
                }
                if (gameState[x, y].piece == Piece.Bishop) SelectBishop(x, y);
                if (gameState[x, y].piece == Piece.Queen) SelectQueen(x, y);
                if (gameState[x, y].piece == Piece.Tower) SelectTower(x, y);
                if (gameState[x, y].piece == Piece.King) SelectKing(x, y);
                if (gameState[x, y].piece == Piece.Horse) SelectHorse(x, y);
                UpdatePosition();
            }
        }
    }
    bool IsEmpty(int x,int y)
    {
        if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
        {
            return  gameState[x, y].piece == Piece.Empty;
        }
        return false;
    }
    bool SetMoveable(int x,int y,bool takeOnly = false,bool cntTake=false)
    {
        if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
        {
            if (gameState[x, y].piece == Piece.Empty)
            {
                if(!takeOnly)
                gameState[x, y].rs = RenderState.Moveable;
            }
            if(gameState[x, y].piece != Piece.Empty)
            {
                if(gameState[x,y].team != gameState[lsx,lsy].team)
                    gameState[x, y].rs = RenderState.Takeable;
                if (cntTake)
                    gameState[x, y].rs = RenderState.Empty;

            }
            return true;
        }
        return false;
    }

    void ClearState()
    {
        for (int x = 0; x < 8; x++)
        {
            for (int y = 0; y < 8; y++)
            {
                gameState[x, y].rs = RenderState.Empty;
                gameState[x, y].selected = false;
            }
        }
    }
    public void FinshGame()
    {
        ClearState();
        UpdatePosition(true);

        gm.Click_L();
        gm.GameFinished();
        Start();
    }
    public void Move(int x,int y,int to_x,int to_y)
    {
        if (gameState[x, y].piece == Piece.Pawn)
        {
            if (to_x == 0)
            {
                Transform t = gameState[x, y].refrence.transform;
                gameState[x, y].piece = Piece.Queen;
                gameState[x, y].refrence.transform.GetChild(0).GetComponent<MeshFilter>().mesh = queenMesh;
                //gameState[x, y].refrence = Instantiate(piecesWhite[(int)Piece.Queen], t.position, t.transform.rotation, transform);
            }
            if (to_x == 7)
            {
                Transform t = gameState[x, y].refrence.transform;
                gameState[x, y].piece = Piece.Queen;
                gameState[x, y].refrence.transform.GetChild(0).GetComponent<MeshFilter>().mesh = queenMesh;
                //gameState[x, y].refrence = Instantiate(piecesBlack[(int)Piece.Queen], t.position, t.transform.rotation, transform);
            }
        }
        if (gameState[to_x, to_y].piece != Piece.Empty)
        {
            if (gameState[to_x, to_y].team == Team.Black)
            {
                Taken_B.Add(gameState[to_x, to_y].refrence);
            }
            if (gameState[to_x, to_y].team == Team.White)
            {
                Taken_W.Add(gameState[to_x, to_y].refrence);
            }
            if (gameState[to_x, to_y].piece == Piece.King)
            {
                if (selfTeam == gameState[to_x, to_y].team)
                {
                    a.clip = audios[(int)Audio.Lose];
                    a.Play();
                }
                else
                {
                    a.clip = audios[(int)Audio.Win];
                    a.Play();
                }
                ClearState();
                UpdatePosition(true);

                gm.Click_L();
                gm.GameFinished();
                Start();
                return;
            }
        }
        gameState[to_x, to_y].piece = gameState[x, y].piece;
        gameState[to_x, to_y].team = gameState[x, y].team;
        gameState[to_x, to_y].refrence = gameState[x, y].refrence;
        gameState[x, y].refrence = null;
        gameState[x, y].piece = Piece.Empty;
        gameState[to_x, to_y].animate = true;
        gameState[x, y].animate = true;
        ClearState();
        gameState[x, y].selected = true ;
        gameState[to_x, to_y].selected = true;

        escape = true;
        UpdatePosition();
    }
    public void PlaySoundID(Audio au)
    {
        a.clip = audios[(int)au];
        a.Play();
        escape = false;
    }
    #region PawnAction
    void SelectPawn_B(int x,int y)
    {
        SetMoveable(x + 1, y,false,true);
        if(x==1 && IsEmpty(2, y))
            SetMoveable(x+2, y,false, true);
        SetMoveable(x + 1, y - 1, true);
        SetMoveable(x + 1, y + 1, true);
    }
    void SelectPawn_W(int x, int y)
    {
        SetMoveable(x - 1, y, false, true);
        if (x == 6 && IsEmpty(5,y))
            SetMoveable(x - 2, y, false, true);
        SetMoveable(x - 1, y - 1, true);
        SetMoveable(x - 1, y + 1, true);
    }
    void SelectBishop(int x, int y)
    {
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x + i, y+i, false, false);
            if (!IsEmpty(x+i,y+i))
                break;
        }
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x + i, y - i, false, false);
            if (!IsEmpty(x + i, y - i))
                break;
        }
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x - i, y + i, false, false);
            if (!IsEmpty(x - i, y + i))
                break;
        }
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x - i, y - i, false, false);
            if (!IsEmpty(x - i, y - i))
                break;
        }
    }
    void SelectHorse(int x, int y)
    {
        SetMoveable(x + 2, y + 1, false, false);
        SetMoveable(x + 2, y - 1, false, false);

        SetMoveable(x - 2, y + 1, false, false);
        SetMoveable(x - 2, y - 1, false, false);

        SetMoveable(x + 1, y - 2, false, false);
        SetMoveable(x - 1, y - 2, false, false);

        SetMoveable(x + 1, y + 2, false, false);
        SetMoveable(x - 1, y + 2, false, false);
    }

    void SelectKing(int x, int y)
    {
        SetMoveable(x + 1, y + 0, false, false);
        SetMoveable(x + 1, y + 1, false, false);
        SetMoveable(x + 1, y - 1, false, false);

        SetMoveable(x + 0, y - 1, false, false);
        SetMoveable(x + 0, y + 1, false, false);

        SetMoveable(x - 1, y + 0, false, false);
        SetMoveable(x - 1, y - 1, false, false);
        SetMoveable(x - 1, y + 1, false, false);
    }

    void SelectQueen(int x, int y)
    {
        SelectKing(x,y);
        SelectBishop(x, y);
        SelectTower(x, y);
    }

    void SelectTower(int x, int y)
    {
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x + i, y, false, false);
            if (!IsEmpty(x + i, y))
                break;
        }
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x , y+i, false, false);
            if (!IsEmpty(x, y+i))
                break;
        }
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x - i, y, false, false);
            if (!IsEmpty(x- i, y))
                break;
        }
        for (int i = 1; i < 8; i++)
        {
            SetMoveable(x, y -i, false, false);
            if (!IsEmpty(x, y - i))
                break;
        }

    }
    #endregion
    void Start()
    {
        a = GetComponent<AudioSource>();
        MSelect = new Material(rawMaterial);
        MMoveable = new Material(rawMaterial);
        MTakeable = new Material(rawMaterial);
        MSelect.SetTexture("_BaseMap", TSelect);
        MMoveable.SetTexture("_BaseMap", TMoveable);
        MTakeable.SetTexture("_BaseMap", TTakeable);
        MSelect.SetTexture("_MainTex", TSelect);
        MMoveable.SetTexture("_MainTex", TMoveable);
        MTakeable.SetTexture("_MainTex", TTakeable);
        for (int x = 0; x < 8; x++)
        {
            for (int y = 0; y < 8; y++)
            {
                grids[x, y] = Instantiate(grid,transform);
                grids[x, y].transform.position = new Vector3(0.4991f-0.1425f*x,0.0004f, 0.4991f - 0.1425f * y);
                grids[x, y].transform.eulerAngles = new Vector3(-90,0,0);
                grids[x, y].name = x + "," + y;
            }
        }
        Initiate();
    }

    // Update is called once per frame
    void Update()
    {
        if (queenMesh == null)
        {
            queenMesh = gameState[0, 3].refrence.transform.GetChild(0).GetComponent<MeshFilter>().mesh;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //Debug.Log(piecesBlack[(int)Piece.Queen].transform.GetChild(0).GetComponent<MeshFilter>().mesh.triangles.Length);
        }
        //Input.touches[0].position
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            if (Physics.Raycast(ray, out hitInfo))
            {
                //Debug.DrawLine(ray.origin, hitInfo.point);
                GameObject gameObj = hitInfo.collider.gameObject;
                if (gameObj.tag == "Grid"  && Input.GetButtonUp("Fire1") && selfTeam == turn)
                {
                    //Debug.Log(gameObj.name + " was picked.");
                    UIText.text = gameObj.name;
                    int x = Convert.ToInt32(gameObj.name.Substring(0,1));
                    int y = Convert.ToInt32(gameObj.name.Substring(2, 1));
                    SelectGrid(x, y);
                }
                Selected.transform.position = gameObj.transform.position;
                Selected.transform.Translate(new Vector3(0,0.0005f,0));
            }
        }
    }
}
public enum Piece
{
    Bishop = 0,
    Horse = 1,
    King = 2,
    Pawn = 3,
    Queen = 4,
    Tower = 5,
    Empty = -1
}

public enum Audio
{
    Check = 0,
    Illegal = 1,
    Lose = 2,
    Win = 3,
    Take= 4,
    Move = 5,
}
