// 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.Reflection;
using System.Globalization;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Gtk;

using Hiperscan.Spectroscopy;
using Hiperscan.FileIO;
using Hiperscan.Unix;


namespace Hiperscan.Extensions
{

	public abstract class PluginInfo
	{
		protected string label;
		protected bool watch_cursor = false;
		protected bool need_idle_device = false;
		protected bool need_unprogrammed_or_idle_device = false;
		protected bool need_single_device = false;
		protected bool is_toggle = false;
		protected bool is_sensitive = true;

		public event EventHandler<EventArgs> Invoked;
		
		protected PluginInfo() {}

		public void Invoke(object sender, EventArgs e)
		{
			if (this.Invoked != null)
				this.Invoked(sender, e);
		}

		public string Label
		{
			get { return this.label; }
		}
		
		public bool WatchCursor
		{
			get { return this.watch_cursor;  }
			set { this.watch_cursor = value; }
		}

		public bool NeedIdleDevice
		{
			get { return this.need_idle_device;  }
			set { this.need_idle_device = value; }
		}
		
		public bool NeedUnprogrammedOrIdleDevice
		{
			get { return this.need_unprogrammed_or_idle_device;  }
			set { this.need_unprogrammed_or_idle_device = value; }
		}

		public bool NeedSingleDevice
		{
			get { return this.need_single_device;  }
			set { this.need_single_device = value; }
		}
		
		public bool IsToggle
		{
			get { return this.is_toggle;  }
			set { this.is_toggle = value; }
		}
		
		public bool IsSensitive
		{
			get { return this.is_sensitive;  }
			set { this.is_sensitive = value; }
		}
	}
	
	public class MenuInfo : PluginInfo
	{
		private MenuItem menu_item = null;
		private MenuItem submenu_item = null;

		
		public MenuInfo(string label)
		{
			this.label = label;
		}
		
		public MenuItem MenuItem
		{
			get { return this.menu_item;  }
			set { this.menu_item = value; }
		}

		public MenuItem SubMenuItem
		{
			get { return this.submenu_item;  }
			set { this.submenu_item = value; }
		}
	}
	
	public class ToolbarInfo : PluginInfo
	{
		private ToolItem tool_item;
		private string   tooltip;

		
		public ToolbarInfo(ToolItem tool_item, string label, string tooltip)
		{
			this.tool_item = tool_item;
			this.label     = label;
			this.tooltip   = tooltip;
		}
		
		public Widget ToolItem
		{
			get { return this.tool_item; }
		}
		
		public string Tooltip
		{
			get { return this.tooltip; }
		}
	}
	
	abstract public class PlotTypeInfo
	{
		private string name;
		private string xlabel = "x";
		private string ylabel = "y";
		
		private double lower_limit = -2f;
		private double upper_limit = 5f;
		private double standard_min = -0.1f;
		private double standard_max = 2.6f;
		
		private bool need_absorbance;
		private bool active;
		private bool interdependent;
		
		
		public PlotTypeInfo(string name)
		{
			this.name = name;
			this.active = true;
			this.interdependent = false;
		}
		
		public virtual int GetPlotTypeId()
		{
			return this.GetType().ToString().GetHashCode();
		}
		
		public virtual DataSet ComputeDataSet(Spectrum spectrum, DataSet.XConstraints x_constraints)
		{
			return spectrum.Intensity;
		}
		
		public virtual bool QueryInformation()
		{
			return true;
		}
		
		public virtual void Reset()
		{
		}
		
		public virtual string Name
		{
			get { return this.name;  }
			set { this.name = value; }
		}
		
		public virtual string XLabel
		{
			get { return this.xlabel;  }
			set { this.xlabel = value; }
		}
		
		public virtual string YLabel
		{
			get { return this.ylabel;  }
			set { this.ylabel = value; }
		}
		
		public virtual double LowerLimit
		{
			get { return this.lower_limit;  }
			set { this.lower_limit = value; }
		}
		
		public virtual double UpperLimit
		{
			get { return this.upper_limit;  }
			set { this.upper_limit = value; }
		}
		
		public virtual double StandardMin
		{
			get { return this.standard_min;  }
			set { this.standard_min = value; }
		}
		
		public virtual double StandardMax
		{
			get { return this.standard_max;  }
			set { this.standard_max = value; }
		}
		
		public virtual bool NeedAbsorbance
		{
			get { return this.need_absorbance;  }
			set { this.need_absorbance = value; }
		}
		
		public virtual bool Active
		{
			get { return this.active;  }
			set { this.active = value; }
		}
		
		public virtual bool Interdependent
		{
			get { return this.interdependent;  }
			set { this.interdependent = value; }
		}
	}
	
	public enum FileRwType
	{
		ReadOnly,
		WriteOnly,
		ReadWrite
	}
	
	abstract public class FileTypeInfo
	{
		
		private string name;
        private IEnumerable<string>  extensions;
		
		protected bool is_container  = false;
		protected FileRwType rw_type = FileRwType.ReadWrite;
		
		
        public FileTypeInfo(string name, IEnumerable<string> extensions)
		{
			this.name = name;
			this.extensions = extensions;
		}
		
		public virtual Spectrum Read(string fname)
		{
			throw new NotImplementedException();
		}
		
		public virtual void Write(Spectrum spectrum, string fname, CultureInfo culture)
		{
			throw new NotImplementedException();
		}	
		
		public virtual Spectrum[] ReadContainer(string fname, out List<MetaData> meta_data)
		{
			throw new NotImplementedException();
		}
		
		public virtual void WriteContainer(List<Spectrum> spectrum, List<MetaData> meta_data, string fname, CultureInfo culture)
		{
			throw new NotImplementedException();
		}	
		
		public string Name
		{
			get { return this.name; }
		}
		
        public IEnumerable<string> Extensions
		{
			get { return this.extensions; }
		}
		
		public bool IsContainer
		{
			get { return this.is_container; }
		}
		
		public FileRwType RwType
		{
			get { return this.rw_type; }
		}
	}

	
	public interface IPlugin
	{
		void Initialize(IHost host);
		void ReplaceGui();
		
		MenuInfo[] MenuInfos { get; }
		ToolbarInfo[] ToolbarInfos { get; }
		PlotTypeInfo[] PlotTypeInfos { get; }
		FileTypeInfo[] FileTypeInfos { get; }

		string Name { get; }
		string Version { get; }
		string Vendor { get; }
		Assembly Assembly { get; }
		string Description { get; }
		Guid Guid { get; }
		bool Active { get; set; }
		bool CanReplaceGui { get; }
	}
}
