namespace PerpetuumSoft.Widgets
{
    using PerpetuumSoft.Widgets.Licensing;
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;

    [LicenseProvider(typeof(WidgetsLicenseProvider)), ToolboxBitmap(typeof(Matrix))]
    public class Matrix : InstrumentationControl
    {
        private int scrollInterval = 100;
        private TextScrollStyle scrollStyle = TextScrollStyle.RightToLeft;
        private bool scrollText = false;
        private int text_dx = 0;
        private int text_move = 0;
        private int textLenght = 0;
        private Timer timer;

        public Matrix()
        {
            this.BackColor = Color.Black;
            this.ForeColor = Color.Lime;
        }

        private void CreateTimer()
        {
            if (this.timer == null)
            {
                this.timer = new Timer();
                this.timer.Tick += new EventHandler(this.timer_Tick);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (this.timer != null))
            {
                this.timer.Dispose();
                this.timer = null;
            }
            base.Dispose(disposing);
        }

        private void DisposeTimer()
        {
            if (this.timer != null)
            {
                this.timer.Dispose();
                this.timer = null;
            }
        }

        private void DoScroll()
        {
            this.text_dx += this.text_move;
            base.Invalidate();
            if ((this.text_dx < (-this.textLenght - 1)) || (this.text_dx > (1 + (this.WorkRectangle.Width / 3))))
            {
                switch (this.scrollStyle)
                {
                    case TextScrollStyle.RightToLeft:
                        this.text_dx = this.WorkRectangle.Width / 3;
                        return;

                    case TextScrollStyle.LeftToRight:
                        this.text_dx = -this.textLenght;
                        return;

                    case TextScrollStyle.Reverse:
                        this.text_move *= -1;
                        return;

                    default:
                        return;
                }
            }
        }

        protected override void Draw(Graphics g, Rectangle r)
        {
            base.Draw(g, r);
            if ((this.textLenght == 0) && this.ScrollText)
            {
                this.InitScroll(g);
            }
            Rectangle workRectangle = this.WorkRectangle;
            int width = workRectangle.Width / 3;
            int height = workRectangle.Height / 3;
            Bitmap image = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(image);
            graphics.FillRectangle(Brushes.get_Black(), 0, 0, width, height);
            graphics.DrawString(this.Text, this.Font, Brushes.get_White(), (float) (1 + this.text_dx), 1f);
            Brush brush = new SolidBrush(this.ForeColor);
            Brush brush2 = new SolidBrush(Color.FromArgb(this.ForeColor.R / 3, this.ForeColor.G / 3, this.ForeColor.B / 3));
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    Brush brush3;
                    if (image.GetPixel(i, j).R != 0)
                    {
                        brush3 = brush;
                    }
                    else
                    {
                        brush3 = brush2;
                    }
                    g.FillRectangle(brush3, (workRectangle.X + 1) + (i * 3), (workRectangle.Y + 1) + (j * 3), 2, 2);
                }
            }
            graphics.Dispose();
            image.Dispose();
        }

        private void InitScroll(Graphics g)
        {
            this.textLenght = (int) g.MeasureString(this.Text, this.Font).Width;
            switch (this.scrollStyle)
            {
                case TextScrollStyle.RightToLeft:
                    this.text_dx = this.WorkRectangle.Width / 3;
                    this.text_move = -1;
                    return;

                case TextScrollStyle.LeftToRight:
                    this.text_dx = -this.textLenght;
                    this.text_move = 1;
                    return;

                case TextScrollStyle.Reverse:
                    this.text_dx = this.WorkRectangle.Width / 3;
                    this.text_move = -1;
                    return;
            }
        }

        protected override void OnResize(EventArgs e)
        {
            this.ResetScroll();
            base.OnResize(e);
        }

        protected override void OnTextChanged(EventArgs e)
        {
            this.ResetScroll();
            base.Invalidate();
            base.OnTextChanged(e);
        }

        private void ResetScroll()
        {
            this.textLenght = 0;
            this.text_dx = 0;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            this.DoScroll();
        }

        private void UpdateTimerSettings()
        {
            if (this.timer != null)
            {
                this.timer.Interval = this.scrollInterval;
                this.timer.Enabled = this.scrollText;
            }
        }

        [DefaultValue(typeof(Color), "Black")]
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
            }
        }

        protected override Size DefaultSize
        {
            get
            {
                return new Size(200, 100);
            }
        }

        [DefaultValue(typeof(Color), "Lime")]
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
            }
        }

        [Category("Appearance"), Description("Scrolling ticks interval"), DefaultValue(100)]
        public int ScrollInterval
        {
            get
            {
                return this.scrollInterval;
            }
            set
            {
                if (value != this.scrollInterval)
                {
                    this.scrollInterval = value;
                    this.UpdateTimerSettings();
                }
            }
        }

        [DefaultValue(0), Category("Appearance"), Description("Text scrolling direction")]
        public TextScrollStyle ScrollStyle
        {
            get
            {
                return this.scrollStyle;
            }
            set
            {
                if (value != this.scrollStyle)
                {
                    this.scrollStyle = value;
                    this.ResetScroll();
                }
            }
        }

        [DefaultValue(false), Description("Indicate whether text should be scrolled"), Category("Appearance")]
        public bool ScrollText
        {
            get
            {
                return this.scrollText;
            }
            set
            {
                if (value != this.scrollText)
                {
                    this.ResetScroll();
                    this.scrollText = value;
                    if (this.scrollText)
                    {
                        this.CreateTimer();
                    }
                    if (this.timer != null)
                    {
                        this.UpdateTimerSettings();
                    }
                    base.Invalidate();
                }
            }
        }
    }
}
