using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Xml;

namespace EduNetworkBuilder
{
    /// <summary>
    /// For drawing shapes on a network.  Rectangles, circles.  Filled or not
    /// </summary>
    [Serializable]
    public class NetShape
    {
        public NetShapeType MyShape = NetShapeType.none;
        public Rectangle InArea;
        public Color LineColor = Color.Empty;
        public Color FillColor = Color.Empty;
        public string Name = "";
        int DragSize = 15;

        public NetShape(NetShapeType What, Rectangle Where, Color fillcolor, Color linecolor)
        {
            MyShape = What;
            InArea = Where;
            FillColor = fillcolor;
            LineColor = linecolor;
        }
        public NetShape(XmlNode what)
        {
            Load(what);
        }


        public bool Equals(NetShape CompareWith)
        {
            if (MyShape != CompareWith.MyShape) return false;
            if (InArea != CompareWith.InArea) return false;
            if (LineColor != CompareWith.LineColor) return false;
            if (FillColor != CompareWith.FillColor) return false;
            if (Name != CompareWith.Name) return false;
            return true;
        }
        /// <summary>
        /// Draw the specified shape on the image
        /// </summary>
        /// <param name="baseImage"></param>
        public void Draw(Image baseImage, bool InShapeEditMode = false)
        {
            Graphics G = Graphics.FromImage(baseImage);
            Pen trimPen = new Pen(LineColor);
            Brush coloredBrush = new SolidBrush(FillColor);
            switch(MyShape)
            {
                case NetShapeType.circle:
                    if(FillColor != Color.Empty)
                        G.FillEllipse(coloredBrush,InArea);
                    if (LineColor != Color.Empty)
                        G.DrawEllipse(trimPen, InArea);
                    break;
                case NetShapeType.rectangle:
                    if (FillColor != Color.Empty)
                        G.FillRectangle(coloredBrush, InArea);
                    if (LineColor != Color.Empty)
                        G.DrawRectangle(trimPen, InArea);
                    break;
            }
            if(InShapeEditMode)
            {
                int sz = DragSize;
                Color edgeColor = Color.Black;
                if (FillColor == Color.Black) edgeColor = Color.White;
                coloredBrush = new SolidBrush(edgeColor);
                //We want to put drag-marks on the corners of our rectangle
                foreach(Rectangle one in Corners())
                    G.FillRectangle(coloredBrush, one);
                G.DrawImage(Properties.Resources.X, Center());
            }
            G.Dispose();
        }

        List<Rectangle> Corners()
        {
            int sz = DragSize;
            List<Rectangle> tCorners = new List<Rectangle>();
            Rectangle TL = new Rectangle(InArea.X, InArea.Y, sz, sz);
            Rectangle TR = new Rectangle(InArea.X + InArea.Width - sz, InArea.Y, sz, sz);
            Rectangle BL = new Rectangle(InArea.X, InArea.Y + InArea.Height - sz, sz, sz);
            Rectangle BR = new Rectangle(InArea.X + InArea.Width - sz, InArea.Y + InArea.Height - sz, sz, sz);
            tCorners.Add(TL);
            tCorners.Add(TR);
            tCorners.Add(BL);
            tCorners.Add(BR);
            return tCorners;
        }

        //A rectangle in the center of the shape that we can click on
        Rectangle Center()
        {
            int size = 100;
            if (InArea.Width < 200 || InArea.Height < 200)
                size = 50;
            if (InArea.Width < size || InArea.Height < size)
                size = Math.Min(InArea.Width / 2, InArea.Height / 2);
            int cx = InArea.X + (InArea.Width / 2);
            int cy = InArea.Y + (InArea.Height / 2);
            return new Rectangle(cx - (size / 2), cy - (size / 2), size, size);
        }

        public bool CornersAreClickedOn(Point ClickPoint)
        {
            foreach(Rectangle rec in Corners())
            {
                if (rec.Contains(ClickPoint))
                    return true;
            }
            return false;
        }

        public bool CenterIsClickedOn(Point ClickPoint)
        {
            if (Center().Contains(ClickPoint))
                return true;
            return false;
        }

        /// <summary>
        /// return the opposite point from the one clicked on.  This is so we can start
        /// dragging from here.
        /// </summary>
        /// <param name="ClickPoint"></param>
        /// <returns></returns>
        public Point OppositePoint(Point ClickPoint)
        {
            int fX = ClickPoint.X;
            int fY = ClickPoint.Y;
            int halfWidth = InArea.Width / 2;
            int halfHeight = InArea.Height / 2;
            if (ClickPoint.X > InArea.X + halfWidth) fX = InArea.X;
            else fX = InArea.X + InArea.Width;
            if (ClickPoint.Y > InArea.Y + halfHeight) fY = InArea.Y;
            else fY = InArea.Y + InArea.Height;
            return new Point(fX, fY);

        }

        public override string ToString()
        {
            string answer = Name + " " + MyShape.ToString() + " " + LineColor.Name + "/" + FillColor.Name;
            answer = answer + " X:" + InArea.X + " Y:" + InArea.Y;
            answer = answer + "W:" + InArea.Width + " H:" + InArea.Height;
            return answer;
        }

        public void Load(XmlNode theNode)
        {
            foreach (XmlNode Individual in theNode.ChildNodes)
            {
                XmlNodeType myNodetype = Individual.NodeType;
                if (myNodetype == XmlNodeType.Element)
                {
                    switch (Individual.Name.ToLower())
                    {
                        case "name":
                            Name = Individual.InnerText;
                            break;
                        case "what":
                            MyShape = NB.TryParseEnum<NetShapeType>(Individual.InnerText, NetShapeType.none);
                            break;
                        case "where":
                            RectangleConverter converter = new RectangleConverter();
                            InArea = (Rectangle)converter.ConvertFromString(Individual.InnerText);
                            break;
                        case "fillcolor":
                            FillColor = Color.FromName(Individual.InnerText);
                            break;
                        case "linecolor":
                            LineColor = Color.FromName(Individual.InnerText);
                            break;
                    }
                }
            }
        }

        public void Save(XmlWriter writer)
        {
            writer.WriteStartElement("shape");
            writer.WriteElementString("name", Name);
            writer.WriteElementString("what", MyShape.ToString());
            RectangleConverter converter = new RectangleConverter();
            writer.WriteElementString("where", converter.ConvertToString(InArea));
            writer.WriteElementString("fillcolor", FillColor.Name);
            writer.WriteElementString("linecolor", LineColor.Name);
            writer.WriteEndElement();
        }
    }
}
