using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Asa
{
    public class InputDisplay
    {
        private bool _isrun;
        private int _count;
        private PictureBox _pic;
        private RectangleF[] _rect;
        private RectangleF[] _rectText;
        private IOModule.Box_Sta[] _state;
        private string[] _text;

        private const int RADIUS = 20;
        private readonly Font TEXT_FONT = new Font("Arial", 14f, FontStyle.Bold);
        private readonly Color BACK_COLOR = Color.FromArgb(30, 30, 30);
        private readonly SolidBrush RING_ON = new SolidBrush(Color.FromArgb(10, 190, 10));
        private readonly SolidBrush RING_OFF = new SolidBrush(Color.FromArgb(220, 10, 10));
        private readonly SolidBrush RING_NO = new SolidBrush(Color.FromArgb(180, 180, 180));
        private readonly SolidBrush TEXT_BRUSH = new SolidBrush(Color.FromArgb(240, 240, 240));

        public InputDisplay(PictureBox pic)
        {
            _pic = pic;
            pic.Resize += Pic_Resize;
            pic.Paint += Pic_Paint;
        }



        public bool IsRun
        {
            set
            {
                _isrun = value;
                _pic.Refresh();
            }
            get
            {
                return _isrun;
            }
        }

        public void SetState(IOModule.Box_Sta[] sta)
        {
            int min = sta.Length < _state.Length ? sta.Length : _state.Length;
            Array.Copy(sta, 0, _state, 0, min);
            _pic.Refresh();
        }

        public void SetCount(int count)
        {
            _count = count;
            _rect = new RectangleF[count];
            _rectText = new RectangleF[count];
            _text = new string[count];
            _state = new IOModule.Box_Sta[count];

            for (int i = 0; i < count; i++)
                _text[i] = (i + 1).ToString();

            CalcSize();
            _pic.Refresh();
        }

        private void CalcSize()
        {
            int col = 8;
            int row = Convert.ToInt32(Math.Ceiling((float)_count / col));
            float w = (float)_pic.ClientSize.Width / (col + 1);
            float h = (float)_pic.ClientSize.Height / (row + 1);
            float x = 0, y = 0;
            Graphics g = _pic.CreateGraphics();

            _rect = new RectangleF[_count];
            for (int i = 0; i < _count; i++)
            {
                if (i % col == 0)
                {
                    x = w;
                    y += h;
                }
                else
                {
                    x += w;
                }
                _rect[i] = new RectangleF(x - RADIUS, y - RADIUS, RADIUS + RADIUS, RADIUS + RADIUS);
                SizeF sf = g.MeasureString(_text[i], TEXT_FONT);
                _rectText[i] = new RectangleF(x - sf.Width / 2f, y - sf.Height / 2f + 1, sf.Width, sf.Height);
            }

        }

        private void Pic_Resize(object sender, EventArgs e)
        {
            CalcSize();
            _pic.Refresh();
        }

        private void Pic_Paint(object sender, PaintEventArgs e)
        {
            BufferedGraphicsContext current = BufferedGraphicsManager.Current;
            BufferedGraphics bg = current.Allocate(e.Graphics, e.ClipRectangle);
            Graphics g = bg.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.Clear(BACK_COLOR);

            for (int i = 0; i < _rect.Length; i++)
            {
                if (_isrun)
                    g.FillEllipse(_state[i] == IOModule.Box_Sta.On ? RING_ON : RING_OFF, _rect[i]);
                else
                    g.FillEllipse(RING_NO, _rect[i]);
                g.DrawString(_text[i], TEXT_FONT, TEXT_BRUSH, _rectText[i]);
               
            }

            bg.Render();
            bg.Dispose();
        }

    }


    public class OutputDisplay
    {
        private bool _isrun;
        private int _count;
        private PictureBox _pic;
        private RectangleF[] _rect;
        private RectangleF[] _rectText;
        private IOModule.Box_Sta[] _state;
        private string[] _text;
        private int _over = -1;
        private int _down = -1;

        public event Common.DO_Event DO_Click;

        private const int RADIUS = 20;
        private readonly Font TEXT_FONT = new Font("Arial", 14f, FontStyle.Bold);
        private readonly Color BACK_COLOR = Color.FromArgb(30, 30, 30);
        private readonly SolidBrush RING_ON = new SolidBrush(Color.FromArgb(10, 190, 10));
        private readonly SolidBrush RING_OFF = new SolidBrush(Color.FromArgb(220, 10, 10));
        private readonly SolidBrush RING_NO = new SolidBrush(Color.FromArgb(180, 180, 180));
        private readonly SolidBrush TEXT_BRUSH = new SolidBrush(Color.FromArgb(240, 240, 240));
        
        public OutputDisplay(PictureBox pic)
        {
            _pic = pic;
            pic.MouseMove += Pic_MouseMove;
            pic.MouseDown += Pic_MouseDown;
            pic.MouseUp += Pic_MouseUp;
            pic.Resize += Pic_Resize;
            pic.Paint += Pic_Paint;
        }



        public bool IsRun
        {
            set
            {
                _isrun = value;
                _pic.Refresh();
            }
            get
            {
                return _isrun;
            }
        }

        public void SetState(IOModule.Box_Sta[] sta)
        {
            int min = sta.Length < _state.Length ? sta.Length : _state.Length;
            Array.Copy(sta, 0, _state, 0, min);
            _pic.Refresh();
        }

        public void SetCount(int count)
        {
            _count = count;
            _rect = new RectangleF[count];
            _rectText = new RectangleF[count];
            _text = new string[count];
            _state = new IOModule.Box_Sta[count];

            for (int i = 0; i < count; i++)
                _text[i] = (i + 1).ToString();

            CalcSize();
            _pic.Refresh();
        }

        private void CalcSize()
        {
            int col = 8;
            int row = Convert.ToInt32(Math.Ceiling((float)_count / col));
            float w = (float)_pic.ClientSize.Width / (col + 1);
            float h = (float)_pic.ClientSize.Height / (row + 1);
            float x = 0, y = 0;
            Graphics g = _pic.CreateGraphics();

            _rect = new RectangleF[_count];
            for (int i = 0; i < _count; i++)
            {
                if (i % col == 0)
                {
                    x = w;
                    y += h;
                }
                else
                {
                    x += w;
                }
                _rect[i] = new RectangleF(x - RADIUS, y - RADIUS, RADIUS + RADIUS, RADIUS + RADIUS);
                SizeF sf = g.MeasureString(_text[i], TEXT_FONT);
                _rectText[i] = new RectangleF(x - sf.Width / 2f, y - sf.Height / 2f + 1, sf.Width, sf.Height);
            }

        }

        private void Pic_MouseMove(object sender, MouseEventArgs e)
        {
            int n = -1;
            for (int i = 0; i < _rect.Length; i++)
            {
                if (_rect[i].Contains(e.Location))
                {
                    n = i;
                    break;
                }
            }

            if (n != _over)
            {
                _over = n;
                _pic.Refresh();
            }
        }

        private void Pic_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (_down > -1)
                {
                    _down = -1;
                    _pic.Refresh();
                }
            }
        }

        private void Pic_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (_over > -1)
                {
                    _down = _over;
                    _pic.Refresh();
                    if (IsRun) DO_Click?.Invoke(_down);
                }
            }
        }

        private void Pic_Resize(object sender, EventArgs e)
        {
            CalcSize();
            _pic.Refresh();
        }

        private void Pic_Paint(object sender, PaintEventArgs e)
        {
            BufferedGraphicsContext current = BufferedGraphicsManager.Current;
            BufferedGraphics bg = current.Allocate(e.Graphics, e.ClipRectangle);
            Graphics g = bg.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.Clear(BACK_COLOR);

            for (int i = 0; i < _rect.Length; i++)
            {
                if (_isrun)
                {
                    g.FillEllipse(_state[i] == IOModule.Box_Sta.On ? RING_ON : RING_OFF, _rect[i]);
                    if (i == _down)
                        g.DrawRectangle(new Pen(Color.White, 2), _rect[i].X - 3, _rect[i].Y - 3, _rect[i].Width + 6, _rect[i].Height + 6);
                    else if (i == _over)
                        g.DrawRectangle(new Pen(Color.White, 1), _rect[i].X - 3, _rect[i].Y - 3, _rect[i].Width + 6, _rect[i].Height + 6);
                }
                else
                {
                    g.FillEllipse(RING_NO, _rect[i]);
                }
                g.DrawString(_text[i], TEXT_FONT, TEXT_BRUSH, _rectText[i]);
            }

            bg.Render();
            bg.Dispose();
        }

    }


}