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

using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.Security.Cryptography;

namespace CryptoRng
{
    public partial class frm45CryptoRng : Form
    {
        public frm45CryptoRng()
        {
            InitializeComponent();
        }

        private void generateButton_Click(object sender, EventArgs e)
        {
            using (Pen pen = new Pen(Color.Black, 0))
            {
                randomLabel.Text = "";
                rngLabel.Text = "";
                picGraphRandom.Image = null;
                picGraphRNG.Image = null;
                Stopwatch watch = new Stopwatch();
                Cursor = Cursors.WaitCursor;
                Refresh();

                // Generate values with Random.
                int numNumbers = int.Parse(numNumbersTextBox.Text);
                int min = int.Parse(minTextBox.Text);
                int max = int.Parse(maxTextBox.Text);
                Random rand = new Random();
                int[] randNumbers = new int[numNumbers];
                watch.Start();
                for (int i = 0; i < numNumbers; i++)
                    randNumbers[i] = rand.Next(min, max);
                watch.Stop();
                randomLabel.Text = "Random (" + watch.Elapsed.TotalSeconds.ToString("0.00") + " sec)";

                // Display a histogram.
                pen.Color = Color.LightBlue;
                DrawHistogram(picGraphRandom, Brushes.Blue, pen, randNumbers);

                // Generate values with RNGCryptoServiceProvider.
                watch.Restart();
                for (int i = 0; i < numNumbers; i++)
                    randNumbers[i] = RandomInteger(min, max);
                watch.Stop();
                rngLabel.Text = "RNGCryptoServiceProvider (" + watch.Elapsed.TotalSeconds.ToString("0.00") + " sec)";

                // Display a histogram.
                pen.Color = Color.LightGreen;
                DrawHistogram(picGraphRNG, Brushes.Green, pen, randNumbers);

                Cursor = Cursors.Default;
            }
        }

        // The random number provider.
        private RNGCryptoServiceProvider Rand = new RNGCryptoServiceProvider();

        // Return a random integer between a min and max value.
        private int RandomInteger(int min, int max)
        {
            uint scale = uint.MaxValue;
            while (scale == uint.MaxValue)
            {
                // Get four random bytes.
                byte[] fourBytes = new byte[4];
                Rand.GetBytes(fourBytes);

                // Convert that into an uint.
                scale = BitConverter.ToUInt32(fourBytes, 0);
            }

            // Add min to the scaled difference between max and min.
            return (int)(min + (max - min) * (scale / (double)uint.MaxValue));
        }

        // Display a histogram.
        private void DrawHistogram(PictureBox pic, Brush brush, Pen pen, int[] values)
        {
            // Count the values.
            int min = values.Min();
            int max = values.Max();
            int[] counts = new int[max - min + 1];
            for (int i = 0; i < values.Length; i++)
            {
                counts[values[i] - min]++;
            }
            int maxCount = counts.Max();

            // Make a Bitmap.
            Bitmap bm = new Bitmap(pic.ClientSize.Width, pic.ClientSize.Height);
            using (Graphics gr = Graphics.FromImage(bm))
            {
                gr.SmoothingMode = SmoothingMode.AntiAlias;

                // Scale to fit the data.
                RectangleF rect = new RectangleF(0, 0, counts.Length, maxCount);
                PointF[] pts =
                {
                    new PointF(0, pic.ClientSize.Height),
                    new PointF(pic.ClientSize.Width, pic.ClientSize.Height),
                    new PointF(0, 0),
                };
                gr.Transform = new Matrix(rect, pts);

                // Fill the histogram.
                for (int i = 0; i < counts.Length; i++)
                {
                    gr.FillRectangle(brush, i, 0, 1, counts[i]);
                }

                // Draw the histogram.
                if (counts.Length < 200)
                {
                    for (int i = 0; i < counts.Length; i++)
                    {
                        gr.DrawRectangle(pen, i, 0, 1, counts[i]);
                    }
                }
            }

            // Display the histogram.
            pic.Image = bm;
        }


        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.rngLabel = new System.Windows.Forms.Label();
            this.picGraphRNG = new System.Windows.Forms.PictureBox();
            this.randomLabel = new System.Windows.Forms.Label();
            this.picGraphRandom = new System.Windows.Forms.PictureBox();
            this.maxTextBox = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.minTextBox = new System.Windows.Forms.TextBox();
            this.label2 = new System.Windows.Forms.Label();
            this.numNumbersTextBox = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.generateButton = new System.Windows.Forms.Button();
            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
            ((System.ComponentModel.ISupportInitialize)(this.picGraphRNG)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.picGraphRandom)).BeginInit();
            this.tableLayoutPanel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // rngLabel
            // 
            this.rngLabel.Dock = System.Windows.Forms.DockStyle.Fill;
            this.rngLabel.Location = new System.Drawing.Point(3, 143);
            this.rngLabel.Name = "rngLabel";
            this.rngLabel.Size = new System.Drawing.Size(454, 30);
            this.rngLabel.TabIndex = 30;
            this.rngLabel.Text = "RNGCryptoServiceProvider";
            this.rngLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // picGraphRNG
            // 
            this.picGraphRNG.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.picGraphRNG.Dock = System.Windows.Forms.DockStyle.Fill;
            this.picGraphRNG.Location = new System.Drawing.Point(3, 176);
            this.picGraphRNG.Name = "picGraphRNG";
            this.picGraphRNG.Size = new System.Drawing.Size(454, 107);
            this.picGraphRNG.TabIndex = 29;
            this.picGraphRNG.TabStop = false;
            // 
            // randomLabel
            // 
            this.randomLabel.Dock = System.Windows.Forms.DockStyle.Fill;
            this.randomLabel.Location = new System.Drawing.Point(3, 0);
            this.randomLabel.Name = "randomLabel";
            this.randomLabel.Size = new System.Drawing.Size(454, 30);
            this.randomLabel.TabIndex = 28;
            this.randomLabel.Text = "Random";
            this.randomLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // picGraphRandom
            // 
            this.picGraphRandom.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.picGraphRandom.Dock = System.Windows.Forms.DockStyle.Fill;
            this.picGraphRandom.Location = new System.Drawing.Point(3, 33);
            this.picGraphRandom.Name = "picGraphRandom";
            this.picGraphRandom.Size = new System.Drawing.Size(454, 107);
            this.picGraphRandom.TabIndex = 27;
            this.picGraphRandom.TabStop = false;
            // 
            // maxTextBox
            // 
            this.maxTextBox.Location = new System.Drawing.Point(82, 58);
            this.maxTextBox.Name = "maxTextBox";
            this.maxTextBox.Size = new System.Drawing.Size(56, 20);
            this.maxTextBox.TabIndex = 26;
            this.maxTextBox.Text = "100";
            this.maxTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(10, 58);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(30, 13);
            this.label3.TabIndex = 25;
            this.label3.Text = "Max:";
            // 
            // minTextBox
            // 
            this.minTextBox.Location = new System.Drawing.Point(82, 34);
            this.minTextBox.Name = "minTextBox";
            this.minTextBox.Size = new System.Drawing.Size(56, 20);
            this.minTextBox.TabIndex = 24;
            this.minTextBox.Text = "1";
            this.minTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(10, 34);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(27, 13);
            this.label2.TabIndex = 23;
            this.label2.Text = "Min:";
            // 
            // numNumbersTextBox
            // 
            this.numNumbersTextBox.Location = new System.Drawing.Point(82, 10);
            this.numNumbersTextBox.Name = "numNumbersTextBox";
            this.numNumbersTextBox.Size = new System.Drawing.Size(56, 20);
            this.numNumbersTextBox.TabIndex = 22;
            this.numNumbersTextBox.Text = "1000";
            this.numNumbersTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(10, 10);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(62, 13);
            this.label1.TabIndex = 21;
            this.label1.Text = "# Numbers:";
            // 
            // generateButton
            // 
            this.generateButton.Location = new System.Drawing.Point(186, 34);
            this.generateButton.Name = "generateButton";
            this.generateButton.Size = new System.Drawing.Size(75, 23);
            this.generateButton.TabIndex = 20;
            this.generateButton.Text = "Generate";
            this.generateButton.UseVisualStyleBackColor = true;
            this.generateButton.Click += new System.EventHandler(this.generateButton_Click);
            // 
            // tableLayoutPanel1
            // 
            this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.tableLayoutPanel1.ColumnCount = 1;
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel1.Controls.Add(this.randomLabel, 0, 0);
            this.tableLayoutPanel1.Controls.Add(this.picGraphRNG, 0, 3);
            this.tableLayoutPanel1.Controls.Add(this.rngLabel, 0, 2);
            this.tableLayoutPanel1.Controls.Add(this.picGraphRandom, 0, 1);
            this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 63);
            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
            this.tableLayoutPanel1.RowCount = 4;
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.Size = new System.Drawing.Size(460, 286);
            this.tableLayoutPanel1.TabIndex = 31;
            // 
            // frm45CryptoRng
            // 
            this.AcceptButton = this.generateButton;
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(484, 361);
            this.Controls.Add(this.maxTextBox);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.minTextBox);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.numNumbersTextBox);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.generateButton);
            this.Controls.Add(this.tableLayoutPanel1);
            this.Name = "frm45CryptoRng";
            this.Text = "CryptoRng";
            ((System.ComponentModel.ISupportInitialize)(this.picGraphRNG)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.picGraphRandom)).EndInit();
            this.tableLayoutPanel1.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label rngLabel;
        private System.Windows.Forms.PictureBox picGraphRNG;
        private System.Windows.Forms.Label randomLabel;
        private System.Windows.Forms.PictureBox picGraphRandom;
        internal System.Windows.Forms.TextBox maxTextBox;
        internal System.Windows.Forms.Label label3;
        internal System.Windows.Forms.TextBox minTextBox;
        internal System.Windows.Forms.Label label2;
        internal System.Windows.Forms.TextBox numNumbersTextBox;
        internal System.Windows.Forms.Label label1;
        internal System.Windows.Forms.Button generateButton;
        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
    }
}