using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using TheNovel.Properties;
using System.Runtime.InteropServices;

namespace TheNovel
{
	partial class Main : Form
	{
		[DllImport ( "user32.dll" )]
		private static extern short GetAsyncKeyState ( Keys vKey );

		Novel novel;
		Stack<byte []> workdo;
		Stack<byte []> lastworkdo;
		Chapter current;

		bool saveOk = true;
		string savePath = "";

		string lastDoc = "";

		public Novel Novel { get { return novel; } }
		public Chapter Current { get { return current; } }

		public Main ()
		{
			InitializeComponent ();
			Initializing ();
		}

		public Main ( string file )
		{
			InitializeComponent ();
			Initializing ();

			FileStream fs = new FileStream ( file, FileMode.OpenOrCreate, FileAccess.Read );
			Novel.Load ( fs, out novel );
			fs.Close ();

			workdo = new Stack<byte []> ();
			lastworkdo = new Stack<byte []> ();
			current = null;

			saveOk = true;
			savePath = file;

			foreach ( Chapter c in novel )
				ChapterTitles.Items.Add ( c.Title );

			CheckMyState ();
		}

		void Initializing ()
		{
			Langsup.ApplyMain ( this );
			TextEditor.Font = Settings.Default.UserFont;
			SystemTimer.Interval = Settings.Default.SystemPeriod * 1000;
			MenuArs.Checked = Settings.Default.AutoRecoverySystem;
			MenuCcs.Checked = Settings.Default.CloudComputingSystem;
			MenuWps.Checked = Settings.Default.WorkedProtectionSystem;
			MenuPs.Checked = Settings.Default.PublishSystem;
			CheckMyState ();
		}

		public bool IsSaving
		{
			get 
			{
				if ( saveOk )
				{
					return true;
				}
				else
				{
					DialogResult dr = MessageBox.Show ( Langsup.GetWord ( "savequestion" ), Langsup.GetWord ( "msgtitle" ),
						MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question );

					switch ( dr )
					{
						case DialogResult.Yes:
							return SaveFile ();
						case DialogResult.Cancel:
							return false;
						default:
							return true;
					}
				}
			}
		}

		private string GetMyTitle
		{
			get 
			{
				if ( savePath == "" )
					if ( novel != null )
						return Langsup.GetWord ( "untitled" );
					else
						return Langsup.GetWord ( "none" );
				string [] temp = savePath.Split ( '\\' );
				return temp [ temp.Length - 1 ];
			}
		}

		private void SetCurrentState(bool state)
		{
			MenuSafetySave.Enabled = ToolRemoveChapter.Enabled = ToolCut.Enabled =
				ToolCopy.Enabled = ToolPaste.Enabled = MenuCut.Enabled = 
				MenuCopy.Enabled = MenuPaste.Enabled = TextEditor.Enabled =
				ToolSafetySave.Enabled = MenuRemChap.Enabled = state;
		}

		private void SetNovelState ( bool state )
		{
			MenuSave.Enabled = MenuSaveAs.Enabled = MenuClose.Enabled = MenuEdit.Enabled = 
				MenuChapter.Enabled = ToolSave.Enabled = ToolUndo.Enabled = 
				ToolRedo.Enabled = ToolAddChapter.Enabled = ChapterTitles.Enabled = state;
		}

		private void CheckMyState ()
		{
			if ( current == null )
			{
				TextEditor.Text = "";
				SetCurrentState ( false );
			}
			else
			{
				SetCurrentState ( true );
			}

			if ( novel == null )
			{
				ChapterTitles.Items.Clear ();
				SetNovelState ( false );
			}
			else
			{
				SetNovelState ( true );
			}

			NovelInfo.Text = ( novel != null ) ? String.Format ( "{0:}{1:}, {2:}{3:}, {4:yy-MM-dd`hh:mm:ss}",
				Langsup.GetWord ( "titlelabel" ), novel.Title, Langsup.GetWord ( "writerlabel" ), novel.Writer,
				novel.Date ) : Langsup.GetWord ( "none" );
			Text = String.Format ( "[{0:}] - {1:}", GetMyTitle, Langsup.GetWord ( "titlebar" ) );
		}

		public void NewFile ()
		{
			if ( !CloseFile () ) return;

			NewFile newFile = new NewFile ();
			if ( newFile.ShowDialog () == DialogResult.Cancel ) return;

			novel = newFile.GetNewNovel;
			workdo = new Stack<byte []> ();
			lastworkdo = new Stack<byte []> ();
			current = null;

			saveOk = true;
			savePath = "";

			CheckMyState ();
		}

		public void OpenFile ()
		{
			if ( !CloseFile () ) return;

			if ( ofDialog.ShowDialog () == DialogResult.Cancel ) return;
			FileStream fs = new FileStream ( ofDialog.FileName, FileMode.OpenOrCreate, FileAccess.Read );
			Novel.Load ( fs, out novel );
			fs.Close ();

			workdo = new Stack<byte []> ();
			lastworkdo = new Stack<byte []> ();
			current = null;

			saveOk = true;
			savePath = ofDialog.FileName;

			foreach ( Chapter c in novel )
				ChapterTitles.Items.Add ( c.Title );

			CheckMyState ();
		}

		public bool SaveFile ()
		{
			if ( savePath == "" ) return SaveAsFile ();
			FileStream fs = new FileStream ( savePath, FileMode.OpenOrCreate, FileAccess.Write );
			Novel.Save ( fs, novel );
			fs.Close ();
			saveOk = true;

			CheckMyState ();
			return true;
		}

		public bool SaveAsFile ()
		{
			if ( sfDialog.ShowDialog () == DialogResult.Cancel ) return false;
			FileStream fs = new FileStream ( sfDialog.FileName, FileMode.OpenOrCreate, FileAccess.Write );
			Novel.Save ( fs, novel );
			fs.Close ();
			saveOk = true;
			savePath = sfDialog.FileName;

			CheckMyState ();
			return true;
		}

		public bool CloseFile ()
		{
			if ( !IsSaving ) return false;

			novel = null;
			current = null;
			workdo = null;
			ChapterTitles.Items.Clear ();

			saveOk = true;
			savePath = "";

			CheckMyState ();

			return true;
		}

		private void PushDoStack ()
		{
			MemoryStream mem = new MemoryStream ();
			Novel.Save ( mem, novel );
			workdo.Push ( mem.ToArray () );
			lastworkdo.Clear ();
			mem.Close ();
		}

		private void UnDoStack ()
		{
			if ( workdo.Count == 0 ) return;
			MemoryStream mem = new MemoryStream ( workdo.Peek () );
			Novel.Load ( mem, out novel );
			lastworkdo.Push ( workdo.Peek () );
			workdo.Pop ();
			mem.Close ();

			if ( ChapterTitles.Items.Count != novel.Count )
			{
				if ( ChapterTitles.Items.Count < novel.Count )
				{
					for ( int i = 0; i < novel.Count; i++ )
					{
						if ( ChapterTitles.Items [ i ].Text != novel [ i ].Title )
						{
							ChapterTitles.Items.Insert ( i, novel [ i ].Title );
							break;
						}
					}
				}
				else
				{
					for ( int i = 0; i < ChapterTitles.Items.Count; i++ )
					{
						if ( ChapterTitles.Items [ i ].Text != novel [ i ].Title )
						{
							ChapterTitles.Items.RemoveAt ( i );
							break;
						}
					}
				}
			}
		}

		private void ReDoStack ()
		{
			if ( lastworkdo.Count == 0 ) return;
			MemoryStream mem = new MemoryStream ( lastworkdo.Peek () );
			Novel.Load ( mem, out novel );
			workdo.Push ( lastworkdo.Peek () );
			lastworkdo.Pop ();
			mem.Close ();

			if ( ChapterTitles.Items.Count != novel.Count )
			{
				if ( ChapterTitles.Items.Count < novel.Count )
				{
					for ( int i = 0; i < novel.Count; i++ )
					{
						if ( ChapterTitles.Items [ i ].Text != novel [ i ].Title )
						{
							ChapterTitles.Items.Insert ( i, novel [ i ].Title );
							break;
						}
					}
				}
				else
				{
					for ( int i = 0; i < ChapterTitles.Items.Count; i++ )
					{
						if ( ChapterTitles.Items [ i ].Text != novel [ i ].Title )
						{
							ChapterTitles.Items.RemoveAt ( i );
							break;
						}
					}
				}
			}
		}

		private void TextEditor_KeyUp ( object sender, KeyEventArgs e )
		{
			if ( lastDoc != TextEditor.Text )
				PushDoStack ();
			lastDoc = TextEditor.Text;
		}

		private void TextEditor_TextChanged ( object sender, EventArgs e )
		{
			if ( current == null ) return;
			current.Text = TextEditor.Text;
			saveOk = false;
		}

		private void ChapterTitles_DoubleClick ( object sender, EventArgs e )
		{
			if ( ChapterTitles.FocusedItem != null )
			{
				ChangeTitle ( novel [ ChapterTitles.FocusedItem.Index ] );
			}
		}

		public void ChangeTitle ( Chapter chapter )
		{
			current = chapter;
			TextEditor.Text = current.Text;
			CheckMyState ();
		}

		private void SystemTimer_Tick ( object sender, EventArgs e )
		{
			if ( Settings.Default.AutoRecoverySystem )
			{
				FileStream fs = new FileStream ( "backup.bck", FileMode.OpenOrCreate );
				Novel.Save ( fs, novel );
				fs.Close ();
			}

			if ( Settings.Default.WorkedProtectionSystem )
			{
				if ( ( GetAsyncKeyState ( Keys.F11 ) & 0x80 ) != 0 )
				{

				}
			}

			if ( Settings.Default.CloudComputingSystem )
			{ 
			
			}

			if ( Settings.Default.PublishSystem )
			{ 
			
			}

			Application.DoEvents ();
		}
	}
}
