// Created with MonoDevelop
//
//    Copyright (C) 2010 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.



using System;
using System.Collections.Generic;

using Hiperscan.Unix;


namespace Hiperscan.SGS
{

	public abstract partial class Device
	{
		
		public class LUT
		{
			public const int LutLength = 2501;
			
			private float[] data;
			private uint offset;
			private int acquisition_offset;
            private double msa_factor;
			private DateTime date_time;
			private Version firmware_version;
			private Version scan_engine_version;

			private double min_wavelength  = 1000.0;
			private double max_wavelength  = 1900.0;
			private double increment       = 1.0;
			private double extension_range = 10.0;
			
			public LUT(float[] data, uint lut_offset, int acquisition_offset, double msa_factor, DateTime date_time, Version firmware, Version scan_engine)
			{
				this.data                = data;
				this.offset              = lut_offset;
				this.acquisition_offset  = acquisition_offset;
                this.msa_factor          = msa_factor;
				this.date_time           = date_time;
				this.firmware_version    = firmware;
				this.scan_engine_version = scan_engine;
			}
			
			public LUT(double msa, double g, double theta01, double theta2, int acquisition_offset, double msa_factor)
			{
				this.offset = 250000;
				this.acquisition_offset  = acquisition_offset;
                this.msa_factor          = msa_factor;
				this.firmware_version    = new Version(0);
				this.scan_engine_version = new Version(0);
				this.date_time = DateTime.MinValue;

				msa     *= Math.PI / 180.0;
				theta01 *= Math.PI / 180.0;
				theta2  *= Math.PI / 180.0;
				
				this.data = new float[LutLength];

				for (int ix = 0; ix < this.data.Length; ++ix)
				{
					double tau = (double)ix/(double)Device.LUT.LutLength*Math.PI;
					this.data[ix] = (float)(g * Math.Sin(theta01 - msa * Math.Cos(tau)) +
						                    g * Math.Cos(Math.PI/2.0 - theta01 + msa * Math.Cos(tau) - theta2));
				}
			}
			
			public LUT(double msa) : this(msa, 1600.0, 20.0, 15.0, 0, 1.35)
			{
			}
			
            public LUT(double msa, int acquisition_offset, double msa_factor) : this(msa, 1600.0, 20.0, 15.0, acquisition_offset, msa_factor)
			{
				this.acquisition_offset = acquisition_offset;
			}
			
			public float[] Data
			{
				get { return this.data; }
			}
			
			public uint Offset
			{
				get { return this.offset; }
			}	
			
			public int AcquisitionOffset
			{
				get { return this.acquisition_offset; }
			}

            public double MSAFactor
            {
                get { return this.msa_factor;  }
                set { this.msa_factor = value; }
            }
			
			public Version FirmwareVersion
			{
				get { return this.firmware_version; }
			}
			
			public Version ScanEngineVersion
			{
				get { return this.scan_engine_version; }
			}	
			
			public DateTime DateTime
			{
				get { return this.date_time; }
			}

			public double MinWavelength
			{
				get { return this.min_wavelength; }
			}

			public double MaxWavelength
			{
				get { return this.max_wavelength; }
			}

			public double Increment
			{
				get { return this.increment; }
			}

			public double ExtensionRange
			{
				get { return this.extension_range; }
			}
		}
	}
}