using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsControlLibrary1
{
    /// <summary>
    /// Graph object for drawing data to graph.
    /// </summary>
    public partial class Graph : UserControl
    {
        #region Fields
        private Color axisColor;
        private Color dataColor;
        private Color stringColor;
        private Pen penAxis;
        private Pen penData;
        private Point[] pointsAxis;
        private int pointCountX;
        private int pointCountY;
        private int distanceX;
        private int distanceY;
        private int offsetY;
        private int offsetX;
        private Font font;
        private SolidBrush brush;
        private int[] histogram = new int[] { 5, 10, 1, 3, 8, 7, 5, 6, 1, 2, 3, 4, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 2, 2 };
        private object key = new object();//Lock object
        #endregion

        #region Properties
        /// <summary>
        /// Set axis color.
        /// </summary>
        [Description("Set axis colo")]
        public Color AxisColor
        {
            get
            {
                if (axisColor.IsEmpty)
                {
                    this.axisColor = Color.Blue;
                }
                return axisColor;
            }
            set
            {
                axisColor = value;
                SetPenBrush();
                Refresh();
            }
        }
        /// <summary>
        /// Set the color of the data.
        /// </summary>
        [Description("Set data color")]
        public Color DataColor
        {
            get
            {
                if (dataColor.IsEmpty)
                {
                    this.dataColor = Color.Red;
                }
                return dataColor;
            }
            set { dataColor = value; SetPenBrush(); Refresh(); }
        }
        /// <summary>
        /// Collection of data.
        /// </summary>
        [Description("Data collection.")]
        public int[] Histogram
        {
            get { return histogram; }
            set { histogram = value; this.Refresh(); }
        }
        /// <summary>
        /// Color of axis numbers.
        /// </summary>
        [Description("Color of axis numbers")]
        public Color StringColor
        {
            get
            {
                if (stringColor.IsEmpty)
                { stringColor = Color.Red; }
                return stringColor;
            }
            set { stringColor = value; SetPenBrush(); this.Refresh(); }
        }
        #endregion

        /// <summary>
        /// Construct Graph object with size of 320x240
        /// </summary>
        public Graph()
        {
            InitializeComponent();
            this.Width = 640 / 2;
            this.Height = 480 / 2;
            this.distanceX = 10;
            this.distanceY = 10;
            this.offsetY = 10;
            this.offsetX = 10;
            this.font = new System.Drawing.Font("Arial", 10f);
            SetPenBrush();
            SetPoint();
            this.Refresh();
        }
        /// <summary>
        /// Setting parametres for all pens and brushes. This´s needed when the colors of axis, strings ... are changed.
        /// </summary>
        private void SetPenBrush()
        {
            this.brush = new SolidBrush(StringColor);
            this.penAxis = new Pen(AxisColor, 0.5f);
            this.penData = new Pen(DataColor, 0.5f);
        }
        /// <summary>
        /// Creating y and x axis 
        /// </summary>
        private void SetPoint()
        {
            this.pointsAxis = new Point[] 
            {
                new Point(this.distanceX+this.offsetX,this.distanceY), 
                new Point(this.distanceX+this.offsetX,this.Height-this.distanceY-this.offsetY),//Point on position [0,0]
                new Point(this.Width-this.distanceX,this.Height-this.distanceY-this.offsetY)
            };
            this.pointCountX = (-(this.distanceX) + (this.Width - this.distanceX)) / 11;
            this.pointCountY = (-this.distanceY + (this.Height - this.distanceY - this.offsetY)) / 11;
        }
        /// <summary>
        /// Method drwas all graph elements and datas
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            SetPoint();
            e.Graphics.DrawLines(penAxis, pointsAxis);
            for (int i = 0; i < histogram.Length; i++)
            {
                if (i < 11)
                {
                    //Drawinglines on the X axis
                    e.Graphics.DrawLine(
                        penAxis, new Point(i * pointCountX + this.distanceX + this.offsetX, this.Height - this.distanceY - 2 - this.offsetY),
                        new Point(i * pointCountX + this.distanceX + this.offsetX, this.Height - this.distanceY + 2 - this.offsetY));
                    //Draw x axis numbers
                    e.Graphics.DrawString(i.ToString(), this.font, this.brush, i * pointCountX + this.distanceX, this.Height - this.distanceY + 4 - this.offsetY);
                    //Drawing lines on the Y axis
                    e.Graphics.DrawLine(penAxis, new Point(this.distanceX - 2 + this.offsetX, this.Height - i * pointCountY - this.distanceY - this.offsetY),
                        new Point(this.distanceX + this.distanceX - 8 + this.offsetX, this.Height - i * pointCountY - this.distanceY - this.offsetY));
                    //Draw y axis numbers
                    if (i >= 1)
                    {
                        e.Graphics.DrawString(i.ToString(), this.font, this.brush, this.distanceX + this.distanceX - 10 - this.offsetX, this.Height - i * pointCountY - this.distanceY - this.offsetY);
                    }
                }
                //Draw histogram
                if (i < this.histogram.Length)
                {
                    e.Graphics.DrawLine(this.penData, new Point(i * pointCountX / 27 + this.distanceX + this.offsetX, this.Height - this.distanceY - this.offsetY),
                                new Point(i * pointCountX / 27 + this.distanceX + this.offsetX, this.Height - this.distanceY - this.offsetY - this.pointCountY * this.histogram[i]));
                }
            }
            e.Graphics.DrawString("m", this.font, this.brush, 11 * pointCountX + this.distanceX, this.Height - this.distanceY + 4 - this.offsetY);
            e.Graphics.DrawString("*10%", this.font, this.brush, this.distanceX + this.distanceX - 10 - this.offsetX, this.Height - 11 * pointCountY - this.distanceY - this.offsetY);
                   
            base.OnPaint(e);
        }
        /// <summary>
        /// Method creates data for drawing.
        /// </summary>
        /// <param name="data">Drawing data, histogram ...</param>
        public void SetData(int[] data)
        {
            lock (key)
            {
                //for (int i = 0; i < data.Length; i++)
                {
                    this.Histogram =new int[] {10,10,10};
                }
            }
            this.Invalidate();
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);
        }
    }
}
