using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;

namespace VoxelIsometricRenderer
{
    public static class PlayerObject
    {
        static int BlockID = 0;
        static int VoxelID = 0;
        static float PositionX = 0;
        static float PositionY = 0;
        static float PositionZ = 0;
        static int BlockposX = 5;
        static int BlockposY = 16;
        static int BlockposZ =5;
        static float PrecisePositionX = 0.0f;
        static float PrecisePositionY = 0.0f;
        static float PrecisePositionZ = 0.0f;
        static Rectangle CameraCentre = new Rectangle(0,0,100,100);
        static int[] LastPositions = new int[] { 0, -192 };
        static Rectangle PlayerPosition = new Rectangle(0,0,100,100);
        public static int GetVoxelID()
        {
            return VoxelID;
        }
        public static void Draw(Graphics g)
        {
            Chunk PlayerChunk = ChunkRegistry.FetchChunk(String.Format("x={0};y={1};z={2}", (int)Math.Floor(BlockposX / (double)ChunkRegistry.FetchDimensions()[0]), (int)Math.Floor(BlockposY / (double)ChunkRegistry.FetchDimensions()[1]), (int)Math.Floor(BlockposZ / (double)ChunkRegistry.FetchDimensions()[2])));
            BlockRegistry.RenderBlock(g, BlockID, BlockposX, BlockposY, BlockposZ, PlayerChunk != null ? PlayerChunk.SkyLightHeightMap[Math.Max(BlockposX - (PlayerChunk.ChunkPos[0] * ChunkRegistry.FetchDimensions()[0]), 0), Math.Max(BlockposY - (PlayerChunk.ChunkPos[1] * ChunkRegistry.FetchDimensions()[1]), 0), Math.Max(BlockposZ - (PlayerChunk.ChunkPos[2] * ChunkRegistry.FetchDimensions()[2]), 0)] : 1);
            int[] Positions = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX, PositionY, PositionZ);
            if (Positions[0] != LastPositions[0] || Positions[1] != LastPositions[1])
            {
                //MessageBox.Show(Positions[0] + "_" + Positions[1]);
                LastPositions = Positions;
            }
            PlayerPosition = new Rectangle(Positions[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), Positions[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize);
            g.DrawRectangle(new Pen(Brushes.Blue), PlayerPosition);
            g.DrawRectangle(new Pen(Brushes.Red), CameraCentre);
        }
        public static void UpdateCamera()
        {
            if (!CameraCentre.IntersectsWith(PlayerPosition))
            {
                float YPosition = PositionY;
                float XPosition = PositionX;
                float ZPosition = PositionZ;
                int[] Positions = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX, PositionY + 1, PositionZ);
                Rectangle NextPosition = new Rectangle(Positions[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), Positions[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize);
                int[] PositionsX = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX + 1, PositionY, PositionZ - 1);
                Rectangle NextPositionX = new Rectangle(PositionsX[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), PositionsX[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize); 
                if (LightingManager.Square(CameraCentre.Y - PlayerPosition.Y) > LightingManager.Square(CameraCentre.Y - NextPosition.Y) && !CameraCentre.Contains(CameraCentre.X, PlayerPosition.Y))
                {
                    float Iterator = 0;
                    //while (!CameraCentre.Contains(CameraCentre.X,NextPosition.Y) && Iterator < 2)
                    {
                        Iterator+= LightingManager.Square(CameraCentre.Y - NextPosition.Y) <= 10000 ? 0.1f : 1;
                        Positions = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX, PositionY + Iterator, PositionZ);
                        NextPosition = new Rectangle(Positions[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), Positions[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize);
                    }
                    YPosition += Iterator;
                }
                else if (LightingManager.Square(CameraCentre.Y - PlayerPosition.Y) < LightingManager.Square(CameraCentre.Y - NextPosition.Y))
                {
                    float Iterator = 0;
                    //while (!CameraCentre.Contains(CameraCentre.X, NextPosition.Y) && Iterator > -2)
                    {
                        Iterator-= LightingManager.Square(CameraCentre.Y - NextPosition.Y) <= 10000 ? 0.1f : 1;
                        Positions = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX, PositionY + Iterator, PositionZ);
                        NextPosition = new Rectangle(Positions[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), Positions[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize);
                    }
                    YPosition += Iterator;
                }
                if (LightingManager.Square(CameraCentre.X - PlayerPosition.X) < LightingManager.Square(CameraCentre.X - NextPositionX.X) && !CameraCentre.Contains(PlayerPosition.X, CameraCentre.Y))
                {
                    float IteratorX = 0;
                    float IteratorZ = 0;
                    //while (!CameraCentre.Contains(NextPositionX.X, CameraCentre.Y) && IteratorX > -2 && IteratorZ < 2)
                    {
                        IteratorX-= LightingManager.Square(CameraCentre.X - NextPositionX.X) <= 10000 ? 0.1f : 1;
                        IteratorZ+= LightingManager.Square(CameraCentre.X - NextPositionX.X) <= 10000 ? 0.1f : 1;
                        PositionsX = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX + IteratorX, PositionY, PositionZ + IteratorZ);
                        NextPositionX = new Rectangle(PositionsX[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), PositionsX[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize);
                    }
                    XPosition += IteratorX;
                    ZPosition += IteratorZ;
                }
                else if (PlayerPosition.X < CameraCentre.X)
                {
                    float IteratorX = 0;
                    float IteratorZ = 0;
                    //while (!CameraCentre.Contains(NextPositionX.X, CameraCentre.Y) && IteratorZ > -1 && IteratorX < 1)
                    {
                        IteratorX+= LightingManager.Square(CameraCentre.X - NextPositionX.X) <= 10000 ? 0.1f : 1;
                        IteratorZ -= LightingManager.Square(CameraCentre.X - NextPositionX.X) <= 10000 ? 0.1f : 1;
                        PositionsX = BlockRegistry.GetDrawLocation(BlockposX, BlockposY, BlockposZ, PositionX + IteratorX, PositionY, PositionZ + IteratorZ);
                        NextPositionX = new Rectangle(PositionsX[0] + (int)(Terrain4.width / (2 * TextureManager.RenderScale)), PositionsX[1] + (int)(Terrain4.height / (2 * TextureManager.RenderScale)), TextureManager.VoxelSize, TextureManager.VoxelSize);
                    }
                    XPosition += IteratorX;
                    ZPosition += IteratorZ;
                }

                PositionX = XPosition;
                PositionY = YPosition;
                PositionZ = ZPosition;
            }
        }
        public static void UpdateCameraCentre(int Width, int Height)
        {
            CameraCentre = new Rectangle((int)((Width/(2 * TextureManager.RenderScale)) - TextureManager.VoxelSize/6), (int)((Height/ (2 * TextureManager.RenderScale)) - (TextureManager.VoxelSize/6)), (int)(TextureManager.VoxelSize/3), (int)(TextureManager.VoxelSize/3));
        }
        public static void CreatePlayer(int[] Faces, int RenderType, BlockState blockState)
        {
            Voxel voxel = new Voxel(RenderType, Faces[0], Faces[1], Faces[2], Faces[3], Faces[4], Faces[5], blockState.hasBlocksLight());
            int index = VoxelRegistry.VoxelExists(voxel);
            if (index == -1)
            {
                index = VoxelRegistry.IndexVoxel(voxel);
            }
            VoxelID = index;
            Block newBlock = new Block(index, BlockstateRegistry.GetBlockstateIndex(blockState), -1);
            int x = BlockposX;
            int y = BlockposY;
            int z = BlockposZ;
            BlockID = BlockRegistry.CheckInBlock(newBlock, x, y, z);
        }
        public static float[] GetCameraPos()
        {
            return new float[] { PositionX, PositionY, PositionZ };
        }
        public static int[] GetPos()
        {
            return new int[] { BlockposX, BlockposY, BlockposZ };
        }
        public static float[] GetPresicePos()
        {
            return new float[] { PrecisePositionX, PrecisePositionY, PrecisePositionZ };
        }
        public static void SetPos(int[] pos, bool Reoccure)
        {
            BlockposX = pos[0];
            BlockposY = pos[1];
            BlockposZ = pos[2];
            if (Reoccure) SetPrecisePos(new float[] { pos[0], pos[1], pos[2] },false);
        }
        public static void SetPrecisePos(float[] pos, bool Reoccure)
        {
            PrecisePositionX = pos[0];
            PrecisePositionY = pos[1];
            PrecisePositionZ = pos[2];
            if(Reoccure)SetPos(new int[] {(int)pos[0], (int)pos[1],(int)pos[2] },false);
        }
        public static void IncrementPos(int Axis, int Increment) { IncrementPos(Axis, Increment, true); }
        public static void IncrementPos(int Axis, int Increment,bool Reoccure)
        {
            switch (Axis)
            {
                case 0: BlockposX += Increment; break;
                case 1: BlockposY += Increment; break;
                case 2: BlockposZ += Increment; break;
            }
            if (Reoccure) SetPrecisePos(new float[] { (float)BlockposX, (float)BlockposY, (float)BlockposZ },false);
        }
        public static void IncrementPrecisePos(int Axis, float Increment, bool Reoccure)
        {
            switch (Axis)
            {
                case 0: PrecisePositionX += Increment; break;
                case 1: PrecisePositionY += Increment; break;
                case 2: PrecisePositionZ += Increment; break;
            }
            if (Reoccure) SetPos(new int[] {(int)PrecisePositionX, (int)PrecisePositionY, (int)PrecisePositionZ },false);
        }
        public static void SetSpecificPos(int Axis, int Pos, bool Reoccure)
        {
            switch (Axis)
            {
                case 0: BlockposX = Pos; break;
                case 1: BlockposY = Pos; break;
                case 2: BlockposZ = Pos; break;
            }
            if (Reoccure) SetPrecisePos(new float[] { BlockposX, BlockposY, BlockposZ },false);
        }
    }
}
