using System;
using Microsoft.Ink;
using System.IO;
using System.Drawing;
using System.Collections;

namespace MathSpeakWrite
{
	/// <summary>
	/// Used to represent a single sample of handwriting either for training or recognition.
	/// </summary>
	public class HandwritingSample
	{
		public int[] xs, ys;
		public string name;
		/// <summary>
		/// Constructor for creating a handwriting sample from a CIT file.
		/// </summary>
		/// <param name="sr"></param>
		public HandwritingSample(string name, StreamReader sr)
		{
			this.name = name;
			setupFromFile(sr);
		}
		

		/// <summary>
		/// Constructor for creating a sample from ink strokes.
		/// </summary>
		/// <param name="s"></param>
		/// <param name="g"></param>
		/// <param name="ic"></param>
		public HandwritingSample(String name, Strokes s, Graphics g, InkCollector ic) 
		{
			this.name = name;
			setupFromStroke(s, g, ic);	
		}
		
		/// <summary>
		/// Loads the Handwriting sample from a given file
		/// </summary>
		/// <param name="sr"></param>
		private void setupFromFile(StreamReader sr) 
		{
			int i;
			int [][] arr;
			int[] x, y;
			ArrayList realXs, realYs;
			
			arr = RegTest.readMultiLine(sr);
			x = arr[0];
			y = arr[1];
			realXs = new ArrayList();
			realYs = new ArrayList();

			//Used to eliminate the stroke breaks
			for(i=0; i < x.Length; i++)
			{
				if(x[i] == 0 && y[i] == 0)
					continue;
				realXs.Add(x[i]);
				realYs.Add(y[i]);
			}
			
			this.xs = new int[realXs.Count];
			this.ys = new int[realXs.Count];

			for(i=0; i < realXs.Count; i++) 
			{
				this.xs[i] = (int) realXs[i];
				this.ys[i] = (int) realYs[i];
			}
		}
		

		/// <summary>
		/// Loads the handwriting sample from a stroke.
		/// </summary>
		/// <param name="daStrokes"></param>
		/// <param name="g"></param>
		/// <param name="ic"></param>
		private void setupFromStroke(Strokes daStrokes, Graphics g, InkCollector ic) 
		{
			int[] x, y;
			int i;
			ArrayList realXs, realYs;

			realXs = new ArrayList();
			realYs = new ArrayList();
	
			x=CITHandwriting.xCoordsFromStrokes(daStrokes, g, ic);
			y=CITHandwriting.yCoordsFromStrokes(daStrokes, g, ic);

			//Used to eliminate the stroke breaks
			for(i=0; i < x.Length; i++)
			{
				if(x[i] == 0 && y[i] == 0)
					continue;
				realXs.Add(x[i]);
				realYs.Add(y[i]);
			}

			this.xs = new int[realXs.Count];
			this.ys = new int[realXs.Count];

			for(i=0; i < realXs.Count; i++) 
			{
				this.xs[i] = (int) realXs[i];
				this.ys[i] = (int) realYs[i];
			}
		}
		
		/// <summary>
		/// Normalizes to a 100x100 box
		/// </summary>
		public void normalize() 
		{
			int i;
			int maxX=0, minX=99999999, maxY=0, minY=99999999;
			double xmul, ymul;
			for(i=0; i < this.xs.Length; i++) 
			{
				int presx, presy;
				presx = this.xs[i];
				presy = this.ys[i];

				if(presx > maxX)
					maxX = presx;
				if(presx < minX)
					minX = presx;
				if(presy > maxY)
					maxY = presy;
				if(presy < minY)
					minY = presy;
			}

			
			xmul = 100.0 / (maxX - minX);
			ymul = 100.0 / (maxY - minY);
			
			for(i=0; i < this.xs.Length; i++) 
			{
				this.xs[i] = (int) ((this.xs[i] - minX) * xmul);
				this.ys[i] = (int) ((this.ys[i] - minY) * ymul);
			}
		}

		/// <summary>
		/// Normalizes to a rectangular box, making the horizontal dimension 100
		/// </summary>
		public void normalizeRect()
		{
			int i;
			int maxX=0, minX=99999999, maxY=0, minY=99999999;
			double xmul, ymul;
			for(i=0; i < this.xs.Length; i++) 
			{
				int presx, presy;
				presx = this.xs[i];
				presy = this.ys[i];

				if(presx > maxX)
					maxX = presx;
				if(presx < minX)
					minX = presx;
				if(presy > maxY)
					maxY = presy;
				if(presy < minY)
					minY = presy;
			}

			
			xmul = 100.0 / (maxX - minX);
			ymul = 100.0 / (maxY - minY);
			
			for(i=0; i < this.xs.Length; i++) 
			{
				this.xs[i] = (int) ((this.xs[i] - minX) * xmul);
				this.ys[i] = (int) ((this.ys[i] - minY) * xmul);
			}
		}
	}
}
