using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using CaLib.User;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using ClipClop.Model;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using ClipClop.User;
using System.Xml.Serialization;
using System.Runtime.Serialization;

namespace ClipClop.View
{
	public partial class PictureLimitedListBox : LimitedListBox
	{
		public class ImagePair : IDisposable
		{
			public readonly Image original_;
			public readonly Image thumbnail_;

			public ImagePair()
			{ 
			}

			public ImagePair(Image original, Image thumbnail)
			{
				original_ = original;
				thumbnail_ = thumbnail;
			}

			public void Dispose()
			{
				original_.Dispose();
				thumbnail_.Dispose();
			}
		}

		public static readonly string IMAGEDIRECOTRY_ = Path.Combine(AplSetting.APP_DATA_FOLDER_, "Image");

		public PictureLimitedListBox()
		{
			InitializeComponent();

			Initialize();
		}

		public PictureLimitedListBox(IContainer container)
		{
			container.Add(this);

			InitializeComponent();

			Initialize();
		}

		private void Initialize()
		{
			Directory.CreateDirectory(IMAGEDIRECOTRY_);
			this.toolStripMenuItem先頭に移動.Click += this.先頭に移動ToolStripMenuItem_Click;
			this.toolStripMenuItem削除.Click += this.削除ToolStripMenuItem_Click;
			this.toolStripMenuItem全て削除.Click += this.全て削除toolStripMenuItem_Click;
			this.toolStripMenuItemファイルに保存.Click += this.ファイルに保存toolStripMenuItem_Click;

			this.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.OnMyDrawItem);

			SetListContextMenuStripEnabled(false);
		}

		static string CreateImageFileName()
		{
			string path;
			while (true)
			{
				string fname = Path.GetTempFileName();
				path = Path.Combine( IMAGEDIRECOTRY_, Path.GetFileName(fname) );

				if (!File.Exists(path))
				{
					break;
				}
			}
			return path;
		}

		public override void InsertHead(object s)
		{ 
			Image original = s as Image;

			int spacing = ClipClop.Properties.Settings.Default.ImageHistorySpacing;

			Image thumbnail = CaLib.User.ImageUtil.CreateThumbnail(
				  original,
				  this.ClientSize.Width - spacing * 2,
				  this.ItemHeight - spacing * 2,
				  spacing);

			// 保存しないことにする
			//string path = CreateImageFileName();
			//original.Save(path);//TODO pngで保存される。そのまま保存したい。
			//Trace.WriteLine("saved image to " + path );

			base.InsertHead(new ImagePair(original, thumbnail)); // 画像の追加
		}

		//public bool InsertImage(Image original)
		//{
		//    //TODO　別スレッド
		//    int spacing = ClipClop.Properties.Settings.Default.ImageHistorySpacing;
		//    Image thumbnail = CaLib.User.ImageUtil.CreateThumbnail(
		//          original,
		//          this.ClientSize.Width - spacing * 2,
		//          this.ItemHeight - spacing * 2,
		//          spacing);
		//    int ret = this.Items.Add(thumbnail); // 画像の追加
		//    return true;
		//}

		private void OnMyDrawItem(object sender, DrawItemEventArgs e)
		{
			if (e.Index == -1) // 項目がない場合にも呼び出される
				return;

			if (e.Index >= this.Items.Count)
				return;


			//項目の背景を背景色で塗りつぶす。
			//選択されている項目に対しては強調表示のための色で塗りつぶされる。
			//このメソッドは画像を描画する前に呼び出す必要がある。
			e.DrawBackground();

			object ob = this.Items[e.Index];

			Image thumbnail = ((ImagePair)ob).thumbnail_;
			// 画像を中央に表示
			e.Graphics.DrawImage(thumbnail,
			  e.Bounds.X + (e.Bounds.Width - thumbnail.Width) / 2,
			  e.Bounds.Y + (e.Bounds.Height - thumbnail.Height) / 2);

			//描画している項目にフォーカスがある場合に、それを示す四角形（枠）を描画する
			//（初期状態などではフォーカスがあっても選択されているとは限らない）
			e.DrawFocusRectangle();
		}


		/// <summary>
		/// RemoveOldでアイテムが削除されるときに呼ばれます。
		/// </summary>
		/// <param name="s"></param>
		public override void OnRemoveItem(object s, int index)
		{
			ImagePair p = s as ImagePair;

			try
			{
				p.Dispose();
			}
			catch( Exception exp )
			{
				Trace.WriteLine( exp.Message );
				//MessageBox.Show( exp.Message );
			}

			if(this.Items.Count < 1){
				SetListContextMenuStripEnabled(false);
			}
		}


		#region menu

		private void 先頭に移動ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			MoveToHead();
		}

		private void MoveToHead()
		{
			if (this.SelectedIndex < 1)
				return;//先頭は移動なし

			ImagePair s = this.SelectedItem as ImagePair;

			int index = this.SelectedIndex;
			this.Items.RemoveAt(index);

			try
			{
				//TODO 同じ画像がクリップボードに張り付くので第二引数をfalseにした。
				//DataObject data = new DataObject(s.original_);
				//ClipboardAdapter.SetDataObject(data, true);

				//ClipboardAdapter.SetImage(s.original_);

				DataObject data = new DataObject(s.original_);
				ClipboardAdapter.SetDataObject(data, false);
			}
			catch (ExternalException exp)
			{
				//何もしない。
				Trace.WriteLine(exp);
			}
		}

		//private void 改行を削除して先頭へToolStripMenuItem_Click(object sender, EventArgs e)
		//{
		//    listBoxHistory.MoveHead(true);
		//}

		private void 削除ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			DeleteSelectedItem();
		}

		private void 全て削除toolStripMenuItem_Click(object sender, EventArgs e)
		{
			Clear();
		}


		private void ファイルに保存toolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (SelectedIndex < 0)
				return;
			ImagePair s = SelectedItem as ImagePair;

			using (SaveFileDialog d = new SaveFileDialog())
			{
				d.DefaultExt = "png";
				d.OverwritePrompt = true;
				d.InitialDirectory = string.IsNullOrEmpty(ClipClop.Properties.Settings.Default.InitialDirectoryImageFile) ?
					string.Empty : ClipClop.Properties.Settings.Default.InitialDirectoryImageFile;
				d.FileName = string.Empty;
				d.Filter = ImageUtil.GetFilter();

				DialogResult ret = d.ShowDialog();
				if (ret != DialogResult.OK)
					return;

				ClipClop.Properties.Settings.Default.InitialDirectoryImageFile = Path.GetDirectoryName(d.FileName);

				try
				{
					ImageFormat fmt = ImageUtil.FindImageFormat(Path.GetExtension(d.FileName));

					Trace.WriteLine(string.Format("PictureLimitedListBox.ファイルに保存toolStripMenuItem_Click {0} as {1}", d.FileName, fmt.ToString()));

					//TODO thread
					s.original_.Save(d.FileName, fmt);
				}
				catch (Exception ex)
				{
					Util.ShowError(ex.Message);
				}
			}
		}

		private void SetListContextMenuStripEnabled(bool enable)
		{
			//TODO 同じ関数あり
			foreach (ToolStripItem item in this.ContextMenuStrip.Items)
			{
				item.Enabled = enable;
			}
			ContextMenuStrip.Enabled = enable;

			if (enable == true && SelectedIndex == 0)
			{
				//先頭を選択した場合は移動できない
				this.ContextMenuStrip.Items[0].Enabled = false;
			}
		}

		private void PictureLimitedListBox_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			MoveToHead();
		}

		private void PictureLimitedListBox_SelectedIndexChanged(object sender, EventArgs e)
		{
			//操作メニューの有効無効更新
			if (SelectedIndex < 0)
				SetListContextMenuStripEnabled(false);
			else
				SetListContextMenuStripEnabled(true);

		}

		//private void 編集toolStripMenuItem_Click(object sender, EventArgs e)
		//{
		//}
		#endregion


		public void Save(FileStream fs)
		{
			//TODO 未完
			/*
			XmlSerializer serializer = new XmlSerializer(typeof(ImagePair[]));

			ImagePair[] array = new ImagePair[this.Items.Count];

			this.Items.CopyTo(array, 0);

			serializer.Serialize(fs, array);
			 * */
		}

		private void Read(FileStream fs)
		{
			/*
			XmlSerializer serializer = new XmlSerializer(typeof(ImagePair[]));

			ImagePair[] array = null;

			object o = serializer.Deserialize(fs);

			array = (ImagePair[])o;

			this.Items.Clear();

			for (int idx = array.Length; idx > 0; idx--)
			{
				this.InsertHead(array[idx - 1]);
			}
			 * */
		}

		public void Read(string filepath)
		{
			if (!File.Exists(filepath))
			{
				return;
			}

			using (FileStream fs = new FileStream(filepath, FileMode.Open))
			{
				this.Read(fs);
			}
		}

	}
}
