using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Slayter
{
    public class Hero : MapObject,IDrawable,IMoveable
    {
        private int currentX;
        public int CurrentX { get { return currentX; } }

        private int currentY;
        public int CurrentY { get { return currentY; } }

        public int[] Coordinates{get { return new int[2] {last[1],last[0]}; } }

        public bool heroCanMove;
        public bool heroIsMoving;

        public int leftForTheDay;
        public int possibleMovesForADay;

        GameScreen parent;

        public Texture2D PictureOfHero { get { return picture; } }
        int rrr = 0;
        public int[] position = new int[2] { -1, -1 };
        public int[] last;

        int Frame;
        public Path path;

        public List<Monster> units;

        public Player player;

        const int UncoveredOnMove = 2;

        public Hero(Texture2D pic,Game1 game,int y,int x,Player player)
            :base(pic,new Rectangle(0,0,40,40),game.GameScreen.Bground)
        {
            last = new int[2] { x, y };
            player.Uncover(y,x,UncoveredOnMove);
            units = new List<Monster>();
            heroIsMoving = false;
            heroCanMove = false;
            currentX = 40 * x;
            currentY = 40 * y;
            Frame = 0;
            possibleMovesForADay=Game1.MOVESPERDAY;
            leftForTheDay = Game1.MOVESPERDAY;
            parent = game.GameScreen;
            this.player = player;
            addMonster(new Dragon(parent.parent.Content.Load<Texture2D>("DragonIcon")),10);
            addMonster(new Warrior(parent.parent.Content.Load<Texture2D>("WarriorIcon")), 10);
            path=new Path(null, new Rectangle(0, 0, 0, 0), game.GameScreen.Bground, game, this);
        }

        public bool addMonster(Monster monster,int count)
        {
            for (int i = 0; i < units.Count; i++)
            {
                if(monster.GetType()==units[i].GetType()){
                    units[i].addCount(count);
                    return true;
                }
            }
            if (units.Count <= 4)
            {
                //Console.Out.WriteLine(monster.GetType());
                Monster mon = (Monster)Activator.CreateInstance(monster.GetType(), new object[] { monster.Texture });
                //Monster mon = new Monster(monster);
                mon.addCount(count);
                units.Add(mon);
                return true;
            }
            return false;
        }

        public bool CheckMonsters()
        {
            for (int i = 0; i < units.Count; i++)
            {
                if (units[i].Quantity == 0)
                {
                    units.Remove(units[i]);
                    i--;
                    return true;
                }
            }
            return false;
        }

        public void CheckPlayer()
        {
            if (units.Count == 0)
            {
                player.RemoveHero(this);
            }
        }

        public void UpdateText(){
            parent.UpdateText();
        }

        public void PrintMonsters()
        {
            for (int i = 0; i < units.Count; i++)
            {
                Console.Out.WriteLine("You have "+units[i].Quantity+" of "+units[i].GetType());
            }
        }

        public void setPath(Path path)
        {
            this.path = path;
        }

        public void NewDay()
        {
            player.NewDay();
            UpdateText();
        }

        public void MoveToStart()
        {
            currentX = 0;
            currentY = 0;
        }

        public void AbleToMove(int p)
        {
            if (leftForTheDay - (p+1) >= 0)
            {
                heroCanMove=true;
                return;
            }
            heroIsMoving = false;
            heroCanMove=false;
            map.FirstClick = true;
        }


        public override void draw(SpriteBatch spriteBatch)
        {
            drawHero(spriteBatch);
        }

        public void UpdateCurrent(int[] coordinates)
        {
            if (heroCanMove)
            {
                if (coordinates[0]  * 40 > currentX)
                {
                    currentX += 4;
                }
                else if (coordinates[0] * 40 < currentX)
                {
                    currentX -= 4;
                }

                if (coordinates[1] * 40 > currentY)
                {
                    currentY += 4;
                }
                else if (coordinates[1] * 40 < currentY)
                {
                    currentY -= 4;
                }
            }
        }

        public void hasMoved(int p)
        {
            leftForTheDay -= (p+1);
            UpdateText();
        }

        public void drawHero(SpriteBatch spriteBatch)
        {
            if (path.movesToObject && path.WalkingPath.Count == 1 && heroCanMove)
            {
                map.checkTile(this, path.WalkingPath[0]);
                path.WalkingPath.RemoveAt(0);
                path.DrawingPath.RemoveAt(0);
                heroIsMoving = false;
            }
            else
            {
                UpdateCoordinatesOfMapandHero();
            }
            Rectangle heroRec= new Rectangle(CurrentX, CurrentY, 40, 40);
            Rectangle frame = GetRectangleForFrame();
            if(map.getPosition(ref heroRec,ref frame)){
                /*if (frame.Height != 40)
                {
                    Console.Out.WriteLine(frame.Width+" "+frame.Height);
                    Console.Out.WriteLine(heroRec.Width + " " + heroRec.Height);
                }*/
                spriteBatch.Draw(PictureOfHero, heroRec, frame, Color.White);
            }
        }

        private void UpdateCoordinatesOfMapandHero()
        {
            if (path.WalkingPath.Count != 0 && heroCanMove)
            {
               UpdateCurrent(path.WalkingPath.ElementAt<int[]>(0));
            }
        }

        private Rectangle GetRectangleForFrame()
        {
            Rectangle frame;
            if (path.WalkingPath.Count == 0 || !heroCanMove)
                frame = getFrame(0);
            else
            {
                if (CheckPath(path.WalkingPath.ElementAt<int[]>(0)))
                {
                    last = path.WalkingPath[0];
                    player.Uncover(last[1],last[0],UncoveredOnMove);
                    if (!map.FirstClick && map.hasPath)
                    {
                        path.DrawingPath.RemoveAt(0);
                        if (path.DrawingPath.Count != 0)
                            getHeroDir(path.DrawingPath[0]);
                        else
                            Frame = 0;
                        hasMoved(map.map[path.WalkingPath[0][1], path.WalkingPath[0][0]]);
                    }
                    path.WalkingPath.RemoveAt(0);
                    path.CheckMovement();
                }               
                frame = getFrame(nextFrame());
            }
            return frame;
        }

        public void getHeroDir(int[] p)
        {
            if ( last[0] < p[0])
            {
                Frame = 6;
            }
            else if (last[0] > p[0])
            {
                Frame = 3;
            }
            else if (last[1] > p[1])
            {
                Frame = 9;
            }
            else if (last[1] < p[1])
            {
                Frame=0;
            }
        }


        public Rectangle getFrame(int f)
        {
            int row = f / (PictureOfHero.Width / 40);
            int col = f % (PictureOfHero.Width / 40);
            return new Rectangle(col * 40, row * 40, 40, 40);
        }
        
        public int nextFrame()
        {
            rrr++;
            if (rrr % 4 == 0)
            {
                rrr = 0;
                Frame++;
                if (Frame % 3 == 0)
                {
                    Frame -= 3;
                }
            }
            return Frame;
        }

        private bool CheckPath(int[] coordinates)
        {
            return coordinates[0] * 40 == CurrentX && coordinates[1] * 40 == CurrentY;
        }

        internal void refreshMoves()
        {
            leftForTheDay = possibleMovesForADay; ;
        }

        

        public bool isMovedOn(Hero hero,int[] coor)
        {
            if(hero!=this)
                return coor[0] == last[0] && coor[1] == last[1];
            return false;
        }

        public void Act(GameScreen parent)
        {
            TradeScreen screen=new TradeScreen(parent,player.currentHero,this);
        }
    }
}
