/*
	$Id: Hiyoko.cs 14 2010-01-06 17:27:40Z catwalk $
*/
using System;
using System.Linq;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using System.Configuration;
using System.Threading;
using IronPython.Hosting;
using IronPython.Modules;
using Hiyoko.Forms;
using Hiyoko.Utilities;

namespace Hiyoko{
	public partial class Program : Application{
		private PythonEngine pythonEngine = null;
		private ApplicationSettings settings;
		private CommandLine commandLine;
		
		protected override void OnStartup(StartupEventArgs e){
			if(!ApplicationProcess.IsFirst){
				ApplicationProcess.InvokeRemote("Show");
				this.Shutdown();
			}else{
				ApplicationProcess.Actions.Add("Show", new Action(delegate{
					this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate{
						if(this.MainWindow != null){
							this.MainWindow.Show();
							this.MainWindow.Activate();
						}
					}));
				}));
				//System.Windows.Forms.Application.EnableVisualStyles();
				this.DispatcherUnhandledException += this.HandleUnhandleExceptions;
				
				// コマンドライン
				this.commandLine = new CommandLine();
				
				// 設定読み込み
				this.settings = new ApplicationSettings("Application");
				this.settings.UpgradeOnce();
				if(this.settings.StartupScriptPath == null){
					this.settings.StartupScriptPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\HiyokoStartup.py";
				}
				if(this.settings.IsUseWebProxy){
					Hiyoko.Net.Twitter.TwitterAPI.Proxy = new System.Net.WebProxy(this.settings.WebProxyUri);
				}
				
				// MainForm初期化
				MainForm mainForm = new MainForm();
				this.MainWindow = mainForm;
				if(!(this.settings.IsResident && (this.commandLine.Options.ContainsKey("hide")))){
					mainForm.Show();
				}
				
				// 初期アカウント設定
				if(this.settings.AccessToken == null){
					SettingsForm settings = new SettingsForm();
					settings.Owner = mainForm;
					settings.ShowDialog();
				}
				
				ThreadPool.QueueUserWorkItem(new WaitCallback(delegate{
					// IronPython初期化
					EngineOptions options = new EngineOptions();
					options.ShowClrExceptions = true;
					options.ClrDebuggingEnabled = true;
					options.ExceptionDetail = false;
					this.pythonEngine = new PythonEngine(options);
					this.pythonEngine.LoadAssembly(System.Reflection.Assembly.GetExecutingAssembly());
					ClrModule clr = (ClrModule)this.pythonEngine.Import("clr");
					clr.AddReferenceByPartialName("System");
					clr.AddReferenceByPartialName("System.Core");
					clr.AddReferenceByPartialName("System.Drawing");
					clr.AddReferenceByPartialName("System.Xml");
					clr.AddReferenceByPartialName("System.Xml.Linq");
					clr.AddReferenceByPartialName("System.Web");
					clr.AddReferenceByPartialName("System.Windows.Forms");
					clr.AddReferenceByPartialName("System.Runtime.Remoting");
					clr.AddReferenceByPartialName("WindowsBase");
					clr.AddReferenceByPartialName("PresentationCore");
					clr.AddReferenceByPartialName("PresentationFramework");
					
					// Startupスクリプト実行
					string[] scripts = new string[]{
						this.settings.StartupScriptPath,
						Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + @"\DefaultStartup.py"
					}.Where(file => File.Exists(file)).Take(1).ToArray();
					this.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(delegate{
						MainForm.Outputs.Add(new MessageOutputItem(String.Format("スタートアップスクリプト実行中 - {0}", scripts[0])));
					}));
					if(scripts.Length > 0){
						try{
							string result = null;
							using(MemoryStream standardOutput = new MemoryStream()){
								this.pythonEngine.SetStandardOutput(standardOutput);
								this.pythonEngine.ExecuteFile(scripts[0]);
								result = System.Text.ASCIIEncoding.ASCII.GetString(standardOutput.ToArray());
							}
							this.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(delegate{
								if(!String.IsNullOrEmpty(result)){
									MainForm.Outputs.Add(new MessageOutputItem(result));
								}
								MainForm.Outputs.Add(new SuccessOutputItem("スタートアップスクリプト実行完了"));
							}));
						}catch(Exception ex){
							this.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(delegate{
								mainForm.Outputs.Add(new ErrorOutputItem(this.pythonEngine.FormatException(ex)));
							}));
						}
					}
				}));
			}
			base.OnStartup(e);
		}
		
		protected override void OnExit(ExitEventArgs e){
			base.OnExit(e);
			if(ApplicationProcess.IsFirst){
				this.pythonEngine.Dispose();
				this.settings.Save();
			}
		}
		
		private void HandleUnhandleExceptions(object sender, DispatcherUnhandledExceptionEventArgs e){
			if(e.Exception.GetType().Namespace == "IronPython.Runtime.Exceptions"){
				e.Handled = true;
				if(MessageBox.Show(
					String.Format("IronPythonスクリプトでエラーが発生しました。続行しますか？\n\n{0}", this.pythonEngine.FormatException(e.Exception)),
					"エラー",
					MessageBoxButton.YesNo) == MessageBoxResult.Yes){
				}else{
					this.Shutdown();
				}
			}
		}
		
		public static PythonEngine PythonEngine{
			get{
				Program prog = Application.Current as Program;
				return (prog != null) ? prog.pythonEngine : null;
			}
		}
		
		public static MainForm MainForm{
			get{
				return Application.Current.MainWindow as MainForm;
			}
		}
		
		public static ApplicationSettings Settings{
			get{
				Program prog = Application.Current as Program;
				return (prog != null) ? prog.settings : null;
			}
		}
	}
}