using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;


using Motion6D;

namespace MotionUI
{
    public class SimplePointsIdicator : Panel, IPointsIndicator, DiagramUI.IRedraw
    {

        #region Fields

        public static readonly string name = "Simple";

        protected PositionCollectionIndicator collection;

        private static readonly SimplePointsIdicator Object = new SimplePointsIdicator();

        private Image im;

        protected Brush backBrush = new SolidBrush(Color.Black);

        protected Brush drawBrush = new SolidBrush(Color.White);

        SolidBrush tempBrush = new SolidBrush(Color.White);

        protected double[] auxPos = new double[3];


        protected int dx;

        protected int dy;

        protected int width;

        private static IPointsIndicator indicator = Object;

                    double x1;
            double x2;
            double y1;
            double y2;


        #endregion

        delegate void drawDel();


        #region Ctor

        public SimplePointsIdicator()
        {
            InitializeComponent();
            Dock = DockStyle.Fill;
        }

        #endregion


        


        #region IPointsIndicator Members

        IPointsIndicator IPointsIndicator.this[string name]
        {
            get { return new SimplePointsIdicator(); }
        }

        string[] IPointsIndicator.this[PositionCollectionIndicator collection]
        {
            get { return new string[] { name }; }
        }

        PositionCollectionIndicator IPointsIndicator.Positions
        {
            get
            {
                return collection;
            }
            set
            {
                collection = value;
                Prepare();
            }
        }

        #endregion

        #region IRedraw Members

        void DiagramUI.IRedraw.Redraw()
        {
            draw();
            if (InvokeRequired)
            {
                drawDel d = paint;
                Invoke(d);
                return;
            }
            paint();
        }

        #endregion

  
        #region Specific Members


        void paint()
        {
            Graphics g = Graphics.FromHwnd(Handle);
            g.DrawImage(image, dx, dy);
            g.Dispose();
        }


 
        static public IPointsIndicator Indicator
        {
            get
            {
                return indicator;
            }
            set
            {
                indicator = value;
            }
        }

        protected virtual void Prepare()
        {
            IReferenceFrame f = collection;
            ReferenceFrame frame = f.Own;
            IPositionCollection positions = collection.Positions;
            bool first = true;
            foreach (IPosition p in positions.Positions)
            {
                frame.GetPositon(p, auxPos);
                if (first)
                {
                    x1 = auxPos[0];
                    x2 = x1;
                    y1 = auxPos[1];
                    y2 = y1;
                    first = false;
                    continue;
                }
                double x = auxPos[0];
                double y = auxPos[1];
                if (x < x1)
                {
                    x1 = x;
                }
                if (x > x2)
                {
                    x2 = x;
                }
                if (y < y1)
                {
                    y1 = y;
                }
                if (y > y2)
                {
                    y2 = y;
                }
            }
        }

        private Image image
        {
            get
            {
                if (im == null)
                {
                    createImage();
                }
                return im;
            }
        }

        void createImage()
        {
            width = Width;
            dx = 0;
            dy = 0;
            if (Height < width)
            {
                width = Height;
                dx = (Width - width) / 2;
            }
            else
            {
                dy = (Height - width) / 2;
            }
            im = new Bitmap(width, width);
            draw();
         }

        private void draw()
        {
            int w = im.Width;
            int h = im.Height;
            Graphics g = Graphics.FromImage(im);
            Draw(g, w, h);
            g.Dispose();
        }


        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // SimplePointsIdicator
            // 
            this.AutoSizeChanged += new System.EventHandler(this.SimplePointsIdicator_AutoSizeChanged);
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.SimplePointsIdicator_Paint);
            this.SizeChanged += new System.EventHandler(this.SimplePointsIdicator_SizeChanged);
            this.ResumeLayout(false);

        }

 
 
        private void SimplePointsIdicator_Paint(object sender, PaintEventArgs e)
        {
            Image im = image;
            e.Graphics.DrawImage(im, dx, dy);
        }

        private void SimplePointsIdicator_AutoSizeChanged(object sender, EventArgs e)
        {
            createImage();
        }

        protected virtual void Draw(IPosition position, Graphics g, int x, int y)
        {
            int s = 1;
            Brush br = drawBrush;
            object p = position.Parameters;
            if (p != null)
            {
                if (p is ColorSize)
                {
                    ColorSize cs = p as ColorSize;
                    s = (int)cs.Size;
                    if (s < 1)
                    {
                        s = 1;
                    }
                    tempBrush.Color = cs.Color;
                    br = tempBrush;
                }
            }
            g.FillEllipse(br, x - s, y - s, 2 * s, 2 * s);
        }

        protected void Draw(Graphics g, int w, int h)
        {
            IReferenceFrame f = collection;
            ReferenceFrame frame = f.Own;
            IPositionCollection pos = collection.Positions;
            ICollection<IPosition> l = pos.Positions;
            g.FillRectangle(backBrush, 0, 0, (float)w, (float)h);
            foreach (IPosition p in l)
            {
                frame.GetPositon(p, auxPos);
                double x = auxPos[0];
                double y = auxPos[1];
                int xx = (int)(((x - x1) / (x2 - x1)) * (double)w);
                int yy = (int)(((y - y1) / (y2 - y1)) * (double)h);
                int s = 2;
                Brush br = drawBrush;
                Draw(p, g, xx, yy);
            }
        }

        private void SimplePointsIdicator_SizeChanged(object sender, EventArgs e)
        {
            createImage();
            Refresh();
        }

        #endregion


    }
}
