using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using CoreData.Models;
using CoreData.Helpers;

namespace CoreData.Controllers
{
    public class ChessController : Controller
    {

        public static chessModel listPieces = new chessModel();
        public static List<ColRowHistory> coorhistory = new List<ColRowHistory>();

        public class cor
        {
            public int col { get; set; }
            public int row { get; set; }
        }

        // Make an instance based version of it based on username.
        public ActionResult Index()
        {
            listPieces.pieces.Clear();
            int x1 = 2, x2 = 1;//black pieces
            String color = "Black";

            // first black sequence
            for (int j = 0; j < 2; j++)
            {
                if (j == 1)// second white sequence
                {
                    x1 = 7;
                    x2 = 8;
                    color = "White";
                }

                for (int i = 1; i <= 8; i++)
                {
                    pieces Pieces = new pieces();//pawn
                    Pieces.pawn.col = i;
                    Pieces.pawn.id = i.ToString() + color + Pieces.pawn.name;
                    Pieces.pawn.row = x1;
                    Pieces.pawn.color = color;
                    listPieces.pieces.Add(Pieces.pawn);

                    switch (i)
                    {
                        case 1://rook
                            {
                                Pieces = new pieces();
                                Pieces.rook.id = i.ToString() + color + Pieces.rook.name;
                                Pieces.rook.col = i;
                                Pieces.rook.row = x2;
                                Pieces.rook.color = color;
                                listPieces.pieces.Add(Pieces.rook);
                                break;
                            }
                        case 2://knight
                            {
                                Pieces = new pieces();
                                Pieces.knight.id = i.ToString() + color + Pieces.knight.name;
                                Pieces.knight.col = i;
                                Pieces.knight.row = x2;
                                Pieces.knight.color = color;
                                listPieces.pieces.Add(Pieces.knight); break;
                            }
                        case 3://bishop
                            {
                                Pieces = new pieces();
                                Pieces.bishop.id = i.ToString() + color + Pieces.bishop.name;
                                Pieces.bishop.col = i;
                                Pieces.bishop.row = x2;
                                Pieces.bishop.color = color;
                                listPieces.pieces.Add(Pieces.bishop); break;
                            }
                        case 4://queen
                            {
                                Pieces = new pieces();
                                Pieces.queen.id = i.ToString() + color + Pieces.queen.name;
                                Pieces.queen.col = i;
                                Pieces.queen.row = x2;
                                Pieces.queen.color = color;
                                listPieces.pieces.Add(Pieces.queen); break;
                            }
                        case 5://king
                            {
                                Pieces = new pieces();
                                Pieces.king.id = i.ToString() + color + Pieces.king.name;
                                Pieces.king.col = i;
                                Pieces.king.row = x2;
                                Pieces.king.color = color;
                                listPieces.pieces.Add(Pieces.king); break;
                            }
                        case 6://bishop
                            {
                                Pieces = new pieces();
                                Pieces.bishop.id = i.ToString() + color + Pieces.bishop.name;
                                Pieces.bishop.col = i;
                                Pieces.bishop.row = x2;
                                Pieces.bishop.color = color;
                                listPieces.pieces.Add(Pieces.bishop); break;
                            }
                        case 7://knight
                            {
                                Pieces = new pieces();
                                Pieces.knight.id = i.ToString() + color + Pieces.knight.name;
                                Pieces.knight.col = i;
                                Pieces.knight.row = x2;
                                Pieces.knight.color = color;
                                listPieces.pieces.Add(Pieces.knight); break;
                            }
                        case 8://rook
                            {
                                Pieces = new pieces();
                                Pieces.rook.id = i.ToString() + color + Pieces.rook.name;
                                Pieces.rook.col = i;
                                Pieces.rook.row = x2;
                                Pieces.rook.color = color;
                                listPieces.pieces.Add(Pieces.rook); break;
                            }
                    }
                }
            }

            return View(listPieces);
        }

        // TODO: Figure out how to save ColRowHistory to db
        public String OControl(moveC move, properties piece, Int32? stepSize, String Direction)
        {
            String removeID = "";
            Boolean isMoveable = false;
            List<cor> se = new List<cor>();
            List<properties> ps = new List<properties>();
            var item = new cor();
            int x = piece.row;
            int y = piece.col;

            switch (Direction)
            {
                case "direct":
                    {
                        if (piece.row != move.row && piece.col != move.col) break;

                        if (stepSize == null)//adam says? 
                        {
                            stepSize = Math.Abs(move.col - piece.col) != 0 ? Math.Abs(move.col - piece.col) : Math.Abs(move.row - piece.row);
                        }
                        else
                        {
                            if (Math.Abs(piece.row - move.row) == stepSize || Math.Abs(piece.row - move.row) == 1)//ad?m say?s? belirtilir
                            {
                                stepSize = Math.Abs(piece.row - move.row);
                            }
                            else if (Math.Abs(piece.col - move.col) == stepSize || Math.Abs(piece.col - move.col) == 1)
                            {
                                stepSize = Math.Abs(piece.col - move.col);
                            }
                            else
                            {
                                break;
                            }
                        }

                        for (int i = 1; i <= stepSize; i++)//Moved? I find axis
                        {
                            if (move.row >= piece.row && x + i <= 8 && piece.col == move.col)//x+ 
                            {
                                se.Add(new cor() { col = y, row = x + i });
                            }
                            if (move.row < piece.row && x - i >= 1 && piece.col == move.col)//x-
                            {
                                se.Add(new cor() { col = y, row = x - i });
                            }
                            if (move.col >= piece.col && y + i <= 8 && piece.row == move.row)//y+
                            {
                                se.Add(new cor() { col = y + i, row = x });
                            }
                            if (move.col <= piece.col && y - i >= 1 && piece.row == move.row)//y-
                            {
                                se.Add(new cor() { col = y - i, row = x });
                            }
                        }

                        break;
                    }
                case "cross":
                    {
                        if (piece.row == move.row || piece.col == move.col) break;

                        if (stepSize == null)
                        {
                            stepSize = Math.Abs(move.col - piece.col);
                        }
                        else
                        {
                            if (Math.Abs(piece.row - move.row) != 1 || Math.Abs(piece.col - move.col) != 1)
                            {
                                break;
                            }
                        }

                        for (int i = 1; i <= stepSize; i++)
                        {
                            if (move.row > piece.row && move.col > piece.col && x + i <= 8 && y + i <= 8)//x+ y+
                            {
                                se.Add(new cor() { col = y + i, row = x + i });
                            }
                            if (move.row < piece.row && move.col < piece.col && x - i >= 1 && y - i >= 1)//x- y-
                            {
                                se.Add(new cor() { col = y - i, row = x - i });
                            }
                            if (move.row > piece.row && move.col < piece.col && x + i <= 8 && y - i >= 1)//x+ y-
                            {
                                se.Add(new cor() { col = y - i, row = x + i });
                            }
                            if (move.row < piece.row && move.col > piece.col && x - i >= 1 && y + i <= 8)//x- y+
                            {
                                se.Add(new cor() { col = y + i, row = x - i });
                            }
                        }
                        break;
                    }
                case "L":
                    {
                        if (move.col == y + 1 && move.row == x + 2 && x + 2 <= 8 && y + 1 <= 8)//y+1 x+2
                        {
                            se.Add(new cor() { col = y + 1, row = x + 2 });
                        }
                        if (move.col == y + 1 && move.row == x - 2 && x - 2 >= 1 && y + 1 <= 8)//y+1 x-2
                        {
                            se.Add(new cor() { col = y + 1, row = x - 2 });
                        }

                        if (move.col == y + 2 && move.row == x + 1 && x + 1 <= 8 && y + 2 <= 8)//y+2 x+1
                        {
                            se.Add(new cor() { col = y + 2, row = x + 1 });
                        }
                        if (move.col == y + 2 && move.row == x - 1 && x - 1 >= 1 && y + 2 <= 8)//y+2 x-1
                        {
                            se.Add(new cor() { col = y + 2, row = x - 1 });
                        }

                        if (move.col == y - 1 && move.row == x + 2 && x + 2 <= 8 && y - 1 >= 1)//y-1 x+2
                        {
                            se.Add(new cor() { col = y - 1, row = x + 2 });
                        }
                        if (move.col == y - 1 && move.row == x - 2 && x - 2 >= 1 && y - 1 >= 1)//y-1 x-2
                        {
                            se.Add(new cor() { col = y - 1, row = x - 2 });
                        }

                        if (move.col == y - 2 && move.row == x + 1 && x + 1 <= 8 && y - 2 <= 8)//y-2 x+1
                        {
                            se.Add(new cor() { col = y - 2, row = x + 1 });
                        }
                        if (move.col == y - 2 && move.row == x - 1 && x - 1 >= 1 && y - 2 <= 8)//y-2 x-1
                        {
                            se.Add(new cor() { col = y - 2, row = x - 1 });
                        }
                        break;
                    }
                default:
                    break;
            }

            foreach (var direct in se)//It moved? It's on witch axis?
            {
                foreach (var pc in listPieces.pieces)
                {
                    if (direct.row == pc.row && direct.col == pc.col)
                    {
                        ps.Add(pc);
                    }
                }
            }

            if (se.Count > 0)
            {
                if (ps.Count == 0)//In front of the? Movable?
                {
                    if (Direction == "cross" && piece.name == piece.getName.pawn)
                    { }
                    else
                    {
                        isMoveable = true;
                    }
                }

                if (ps.Count == 1 && ps[0].color != piece.color)//in front of?
                {
                    if (Direction == "direct" && piece.name == piece.getName.pawn)
                    { }
                    else
                    {
                        listPieces.pieces.RemoveAll(a => a.id == ps[0].id);//the defeated elements from the list? 
                        removeID = ps[0].id;//was to be deleted on the client side...
                        isMoveable = true;
                    }
                }

                if (isMoveable == true)//if the motion is accepted
                {
                    piece.col = move.col;
                    piece.row = move.row;
                    piece.isStart = true;
                }
            }

            return isMoveable + ";" + removeID;
        }

        public JsonResult moveControl(moveC move)
        {
            var piece = (from pc in listPieces.pieces where pc.id == move.id select pc).FirstOrDefault();
            string result = "", Direction = "";

            Direction = (piece.row == move.row || piece.col == move.col) ? "direct" : "cross";

            switch (piece.name)
            {
                case "pawn"://
                    {
                        int stepSize = piece.isStart == true ? 1 : 2;//2 throw in the first movement one step
                        Boolean backControl = piece.color == piece.getColor.black ? (piece.row - move.row > 0 ? false : true)
                                                                                  : (piece.row - move.row < 0 ? false : true); //can go back?
                        result = backControl == true ? OControl(move, piece, stepSize, Direction) : "false;";//can go back?                                               
                        break;
                    }
                case "rook"://Is movable only in x and y plane
                    {
                        result = OControl(move, piece, null, "direct");
                        break;
                    }
                case "knight"://Is movable back and forth a twos
                    {
                        result = OControl(move, piece, null, "L");
                        break;
                    }
                case "bishop"://Is movabale only in diagonally
                    {
                        result = OControl(move, piece, null, "cross");
                        break;
                    }
                case "queen"://Is movabale in all directions
                    {
                        result = OControl(move, piece, null, Direction);
                        break;
                    }
                case "king"://Is movabale in all directions
                    {
                        result = OControl(move, piece, 1, Direction);
                        break;
                    }
            }
            return Json(result);
        }

        // TODO: Write method for ColRowHistory playback
        // Call this every time, there is a new event in a colrowhistory
        // Probably need to use react.js https://facebook.github.io/react/docs/why-react.html

        // TODO: Write method for selecting opponent
        public JsonResult syncControl()
        {

            string result = "Sync result";
            
            return Json(result);
        }
    }
}