using System;
using System.Collections.Generic;

namespace PlantDemo
{

    public struct Position
    {
        public int Row { get; set; }
        public int Col { get; set; }

        public Position(int row, int col)
        {
            Row = row;
            Col = col;
        }

        public override string ToString()
        {
            return string.Format("({0},{1})", Row, Col);
        }

        public override bool Equals(object obj)
        {
            if (obj is Position)
            {
                Position p = (Position)obj;
                if (Row == p.Row && Col == p.Col)
                    return true;
            }
            return false;
        }

        public override int GetHashCode()
        {
            return Row.GetHashCode() * 100 + Col.GetHashCode();
        }

        public static bool operator ==(Position p1, Position p2)
        {
            return (p1.Row == p2.Row) && (p1.Col == p2.Col);
        }

        public static bool operator !=(Position p1, Position p2)
        {
            return (p1.Row != p2.Row) || (p1.Col != p2.Col);
        }
    }

    class Game
    {
        public int SunScoreMax { get; set; }

        int sunScore;
        public int SunScore { get { return sunScore; } }
        public int Speed { get; set; }

        int rows, cols;
        public int Rows
        {
            get { return rows; }
        }
        public int Cols
        {
            get { return cols; }
        }

        double[,] damages = new double[4, 2] { { 20, 10 }, { 20, 10 }, { 10, 12.5 }, { 12.5, 15 } };
        Type[] BulletTypes = new Type[] { typeof(BulWD), typeof(BulBWD), typeof(BulXQP), typeof(BulQP) };
        Type[] ZombieTypes = new Type[] { typeof(Zombie), typeof(WireZombie) };

        Dictionary<Position, Plant> plants;
        public Dictionary<Position, Plant> Plants
        {
            get { return plants; }
        }

        List<Bullet> bullets;
        public List<Bullet> Bullets
        {
            get { return bullets; }
        }

        List<Zombie> zombs;
        public List<Zombie> Zombies
        {
            get { return zombs; }
        }

        public Game(int sunScoreMax = 2500, int speed = 1, int rows = 6, int cols = 10)
        {
            Speed = speed;
            sunScore = SunScoreMax = sunScoreMax;
            this.rows = rows;
            this.cols = cols;
            plants = new Dictionary<Position, Plant>();
            bullets = new List<Bullet>();
            zombs = new List<Zombie>();
        }

        public void Reset()
        {
            plants.Clear();
            bullets.Clear();
            zombs.Clear();
            sunScore = SunScoreMax;
        }

        public void AddPlant(Position pos, Plant plant)
        {
            sunScore -= plant.Price;
            plant.X = pos.Col * 80;
            plant.Y = pos.Row * 80;
            plant.OnFire += Plant_OnFire;
            plants.Add(pos, plant);
        }

        private void Plant_OnFire(object sender, EventArgs e)
        {
            this.AddBullet((e as FiringBulletEventArgs).Bullet);
        }

        public void AddBullet(Bullet bullet)
        {
            bullet.OnMove += Bullet_OnMove;
            bullets.Add(bullet);
        }

        private void Bullet_OnMove(object sender, EventArgs e)
        {
            Bullet bul = sender as Bullet;
            if (bul == null) return;
            double dam;
            for (int i = zombs.Count - 1; i >= 0; i--)
            {
                dam = damages[Array.IndexOf(BulletTypes, bul.GetType()), Array.IndexOf(ZombieTypes, zombs[i].GetType())];
                if (bul.Overlap(zombs[i]))
                {
                    if (zombs[i].HeathPoint > dam)
                    {
                        zombs[i].HeathPoint -= dam;
                        if (bul is BulBWD) //寒冰减速
                            zombs[i].IsFrozen = true;
                    }
                    else
                    {
                        zombs[i].HeathPoint = 0;
                        zombs.RemoveAt(i);
                    }
                    bul.Destroy();
                    bullets.Remove(bul);
                }
            }
        }

        public void AddZombie(Zombie zomb)
        {
            zombs.Add(zomb);
        }
    }
}
