using System;
using System.IO;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using Microsoft.DirectX.DirectDraw;
using Microsoft.DirectX;

namespace LCD_Display
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	/// 

	public class Form1 : System.Windows.Forms.Form
	{
		//		private Device myDevice;			// DirectDraw Output Device
		//		private SurfaceDescription sdec;	// DirectDraw Drawing Surface description
		//		private Clipper clip;				// Clip the surface to the window
		//		public Surface surfer;				// DirectDraw drawing surface (main surface)
		//		public Surface myImage;				// Background surface to draw to
		private Graphics Draw;				// GDI+ graphics interface
		private bool KeyPressed;			// Indicates whether a key is pressed while drawing
		private System.Drawing.Bitmap state;
		
		/* Structure containing pixel information */
		public struct pixel_type 
		{
			public int color;
			public bool row, screen;
		};


		/* Visual Studio generated form item definitions */
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.OpenFileDialog openFileDialog1;
		private System.Windows.Forms.ColorDialog colorDialog1;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.Timer timer1;
		private System.ComponentModel.IContainer components;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (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.components = new System.ComponentModel.Container();
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
			this.colorDialog1 = new System.Windows.Forms.ColorDialog();
			this.timer1 = new System.Windows.Forms.Timer(this.components);
			// 
			// mainMenu1
			// 
			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem1,
																					  this.menuItem3,
																					  this.menuItem2});
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 0;
			this.menuItem1.Text = "&Open";
			this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 1;
			this.menuItem3.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem4,
																					  this.menuItem5});
			this.menuItem3.Text = "&Render Mode";
			// 
			// menuItem4
			// 
			this.menuItem4.Checked = true;
			this.menuItem4.Index = 0;
			this.menuItem4.RadioCheck = true;
			this.menuItem4.Text = "&Display Off";
			this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
			// 
			// menuItem5
			// 
			this.menuItem5.Index = 1;
			this.menuItem5.RadioCheck = true;
			this.menuItem5.Text = "&GDI+";
			this.menuItem5.Click += new System.EventHandler(this.menuItem5_Click);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 2;
			this.menuItem2.Text = "E&xit";
			this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);
			// 
			// openFileDialog1
			// 
			this.openFileDialog1.Filter = "LCD Data (*.lst)|*.lst|All Files (*.*)|*.*";
			// 
			// timer1
			// 
			this.timer1.Interval = 1;
			this.timer1.Tick += new System.EventHandler(this.timer1_Tick_1);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(513, 513);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
			this.MaximizeBox = false;
			this.Menu = this.mainMenu1;
			this.Name = "Form1";
			this.Opacity = 0.85;
			this.Text = "GPU Tool";
			this.Click += new System.EventHandler(this.Form1_Click);
			this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.Form1_KeyPress);
			this.Load += new System.EventHandler(this.Form1_Load);
			this.DoubleClick += new System.EventHandler(this.Form1_Click);
			this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
			this.Leave += new System.EventHandler(this.Form1_Leave);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		/* Exit menu item click handler */
		private void menuItem2_Click(object sender, System.EventArgs e)
		{
			Application.Exit();
		}

		/* Function to load date. Inputs: filename, variable to store count (reference),
		 * variable to store period (reference) */
		private pixel_type[] load_wave(String filename, ref long count, ref float period)
		{
			StreamReader InputFP;		// Input file stream
			int I = 0;					// Loop counter
			int time;					// Time of pixel
			string junk;					// Junk to ignore
			int screenin, rowin;		// Screen and row flags
			string incolorstr;			// Color (as string)
			string Instr;				// String input from stream
			string[] partial;			// Partial string (after split)
			pixel_type[] Pixel_Ptr;		// Array of pixel type structures
			
			// Open file
			InputFP = File.OpenText(filename);

			// Dispose of the headers
			for (I = 0; I < 10; I++)
			{
				Instr = InputFP.ReadLine();
			}

			// Count the number of pixels in the file
			count = 0;
			while((Instr = InputFP.ReadLine()) != null)
			{
				count++;
			}

			// Allocate an array of pixel structures
			Pixel_Ptr = new pixel_type[count];

			// Reset the file
			count = 0;
			InputFP.Close();
			InputFP = File.OpenText(filename);

			//Parsing header junk again
			for (I = 0; I < 10; I++)
			{
				Instr = InputFP.ReadLine();
			}
			
			do
			{
				//        300  +6     00000100 0 1 
				Instr = InputFP.ReadLine();
				if(Instr != null && Instr.Trim() != "")
				{
					try
					{
						Instr = Instr.TrimStart();
						partial = Instr.Split(" +".ToCharArray(),2);
						time = int.Parse(partial[0]);
						Instr = partial[1];

						Instr = Instr.TrimStart();
						partial = Instr.Split(" ".ToCharArray(),2);
						//junk = int.Parse(partial[0]);
						junk = partial[0];
						Instr = partial[1];
				
						Instr = Instr.TrimStart();
						partial = Instr.Split(" ".ToCharArray(),2);
						incolorstr = partial[0];
						Instr = partial[1];

						Instr = Instr.TrimStart();
						partial = Instr.Split(" ".ToCharArray(),2);
						rowin = int.Parse(partial[0]);

						Instr = partial[1];
						Instr = Instr.TrimStart();
						partial = Instr.Split(" ".ToCharArray(),2);
						screenin = int.Parse(partial[0]);
						if(rowin == 0)
							Pixel_Ptr[count].row = false;
						else
							Pixel_Ptr[count].row = true;

						if(screenin == 0)
							Pixel_Ptr[count].screen = true;
						else
							Pixel_Ptr[count].screen = false;

						// Convert pixel binary string to a byte in memory
						Pixel_Ptr[count].color = 0;
						foreach(char x in incolorstr.ToCharArray())
						{
							Pixel_Ptr[count].color *= 2;
							if(x == '1')
							{
								Pixel_Ptr[count].color++;
							}
						}
						if(junk == "+3")
							count++;
					}
					catch
					{
					}
				}
			}
			while(Instr != null);

			// Close file and return massive array
			InputFP.Close();

			return Pixel_Ptr;
		}

		// This is the render function.
		private void menuItem1_Click(object sender, System.EventArgs e)
		{
			long count = 0;		// Count of current pixel
			float p = 0;		// period (ignored)
			//Pen myPen;			// Pen to draw GDI+ graphics
			pixel_type[] pixels;	// Array of pixels
			int row, col;			// Current row and column
			int screen;			// Current screen number for output
			
			Draw = this.CreateGraphics();	// Create GDI+ interface
			state = new Bitmap(515, 515, Draw);

			if(menuItem4.Checked == false)
			{	// If GDI+
				Draw.Clear(Color.Black);
			}
			//			else
			//			{	// If DirectDraw
			//				myImage.ColorFill(Color.Black);
			//			}
			//			
			// Open dialog and process
			if(openFileDialog1.ShowDialog() == DialogResult.OK)	
			{
				KeyPressed = false;		// Set key press flag to false
				string filename = openFileDialog1.FileName.Substring(0, openFileDialog1.FileName.Length - 4 ) + "_{0:00}.jpg";
				
				// Set cursor to hourglass
				this.Cursor = Cursors.WaitCursor;
				
				// Set window caption to indicate current statud
				this.Text = "GPU Tool - LOADING DATA";
				
				// Open file and import data
				pixels = load_wave(openFileDialog1.FileName, ref count, ref p);
				
				// Render it
				this.Text = "GPU Tool - RENDERING";
				row = 0;
				col = 0;
				screen = 0;
				for(int i = 0; i < count; i++)
				{
					if(pixels[i].screen)
					{	// If new screen flag,						
						// Reset row and column
						row = 0;
						col = 0;
						state.Save(string.Format(filename, screen++), System.Drawing.Imaging.ImageFormat.Jpeg);

					}
					if(pixels[i].row)
					{	// If new row
						col=0;	// Increment row and reset col
						row+=2;
						if(menuItem5.Checked) 
							Draw.DrawImage(state, 0, 0);
					}
				
					// Do the actual drawing
					state.SetPixel(col, row, Color.FromArgb(pixels[i].color,pixels[i].color,pixels[i].color));
					state.SetPixel(col+1, row, Color.FromArgb(pixels[i].color,pixels[i].color,pixels[i].color));
					state.SetPixel(col, row+1, Color.FromArgb(pixels[i].color,pixels[i].color,pixels[i].color));
					state.SetPixel(col+1, row+1, Color.FromArgb(pixels[i].color,pixels[i].color,pixels[i].color));
					col+=2;
					
					if(KeyPressed) break;		// Stop rendering if key is pressed
				}
				state.Save(string.Format(filename, screen++), System.Drawing.Imaging.ImageFormat.Jpeg);
				
			}

			// Return status to normal
			this.Text = "GPU Tool";
			this.Cursor = Cursors.Arrow;
		}

		// Handle a keypress on the form
		private void Form1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
		{
			KeyPressed = true;
		}

		// Handle clicking the form with the mouse
		private void Form1_Click(object sender, System.EventArgs e)
		{
			KeyPressed = true;
		}

		// Initialization code for program startup
		private void Form1_Load(object sender, System.EventArgs e)
		{
			
		}

		// Redraw form if needed
		private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			if (state != null) 
				Draw.DrawImage(state, 0, 0);
		}

		// Define cleanup for program exit
		private void Form1_Leave(object sender, System.EventArgs e)
		{

		}

		// Select GDI+ from rendering menu
		private void menuItem5_Click(object sender, System.EventArgs e)
		{
			menuItem4.Checked = false;
			menuItem5.Checked = true;
		}

		// Select DirectDraw from rendering menu
		private void menuItem4_Click(object sender, System.EventArgs e)
		{
			menuItem4.Checked = true;
			menuItem5.Checked = false;

		}

		int direction = 0;

		// Irrelevant "feature" that pulsates the window opacity
		// This is normally disabled.
		private void timer1_Tick_1(object sender, System.EventArgs e)
		{
			if(this.Opacity > .99)
			{
				direction = 0;
			}
			else if(this.Opacity < .01)
			{
				direction = 1;
			}

			if(direction == 0)
				this.Opacity-=.02;
			else
				this.Opacity+=.02;
		
		}
	}
}

