// Created with MonoDevelop
//
//    Copyright (C) 2018 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.Text.RegularExpressions;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;

using Hiperscan.Unix;


namespace Hiperscan.SGS
{
    [Serializable()]
    public class MotorParameter
    {
        public byte OTPAddress { set; get; }
        public byte Value      { set; get; }
        
		public MotorParameter()
		{
		}

        public MotorParameter(byte otp_address, byte val)
        {
            this.OTPAddress = otp_address;
            this.Value = val;
        }

		public byte[] ToArray()
		{
			return new byte[] { this.OTPAddress, this.Value };
		}
    }
    
	[Serializable()]
	public class FinderConfig
	{
        public List<MotorParameter> MotorParameters { set; get; }

		public byte Dimmer       { set; get; }
		public uint SleepTimeout { set; get; }

		public byte   TemperatureControlVersion { set; get; }
		public byte   TemperatureControlValue   { set; get; }
		public double TemperatureControlTarget  { set; get; }

		public List<byte> VersionBytes         { set; get; }
		public List<byte> VersionByteOverrides { set; get; }



		public FinderConfig()
		{
		}

        public static FinderConfig Read(string fname)
		{
			try
			{
				using (Stream stream = new FileStream(fname, FileMode.Open, FileAccess.Read))
				{
					XmlSerializer serializer = new XmlSerializer(typeof(FinderConfig));
					FinderConfig config = (FinderConfig)serializer.Deserialize(stream);

					if (config == null)
						throw new Exception(Catalog.GetString("Error while deserialization."));

					return config;
				}
			}
			catch (FormatException)
			{
				// FIXME: The following hack is necessary for Mono ARM < Version 3.4, since there is an error in Double.Parse()
				//        This code should be removed if the bugfix in Mono went upstream
				string content;

				using (Stream stream = new FileStream(fname, FileMode.Open, FileAccess.Read))
				{
					using (StreamReader reader = new StreamReader(stream))
					{
						content = reader.ReadToEnd();
					}
				}

				MatchCollection matches = Regex.Matches(content, @">[0-9]+\.*[0-9]*<");

				foreach (Match match in matches)
				{
					double value;

					string[] s = match.ToString().Replace("<", "").Replace(">", "").Split(new char[] {'.'});
					if (s.Length == 1)
					{
						value = double.Parse(s[0]) * 10.0;
					}
					else if (s.Length == 2 && s[1].Length == 1)
					{
						value = double.Parse(s[0]) * 10.0 + double.Parse(s[1]);
					}
					else
					{
						throw new NotImplementedException("Bugfixing for decimal numbers with more than one digits after decimal separator is not supported.");
					}

					content = content.Replace(match.ToString(), ">" + value.ToString("f0") + "<");
				}

				XmlSerializer serializer = new XmlSerializer(typeof(FinderConfig));
				FinderConfig config = (FinderConfig)serializer.Deserialize(new StringReader(content));

				config.TemperatureControlTarget /= 10.0;

				if (config == null)
					throw new Exception(Catalog.GetString("Error while deserialization."));

				return config;
			}
		}

		public static void Write(FinderConfig finder_config, string fname)
		{
			using (Stream stream = new FileStream(fname, FileMode.Create))
			{
				XmlSerializer serializer = new XmlSerializer(typeof(FinderConfig));
				serializer.Serialize(stream, finder_config);
			}
		}

		public static void CreateTemplate(string fname)
		{
			FinderConfig config = new FinderConfig();

			// default config values
			config.MotorParameters = new List<MotorParameter>();
			config.MotorParameters.Add(new MotorParameter(3, 172));
			config.MotorParameters.Add(new MotorParameter(4, 1));
			config.MotorParameters.Add(new MotorParameter(5, 1));
			config.MotorParameters.Add(new MotorParameter(7, 12));

			// disable I2C address parameter
			//this.MotorParameters.Add(new MotorParameter(2, 0));

			config.Dimmer = 107;
			config.SleepTimeout = 0;

			config.TemperatureControlVersion = 1;
			config.TemperatureControlValue   = 140;
			config.TemperatureControlTarget  = 55.5;

			config.VersionBytes         = new List<byte> {   3,   7,   4,   5 };
			config.VersionByteOverrides = new List<byte> { 255, 255, 255, 255 };

            FinderConfig.Write(config, fname);
		}
	}
}