using System;
using System.IO;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Windows.Forms;

namespace VisualStudioTracAddIn
{
    /// <summary>アドインを実装するためのオブジェクトです。</summary>
    /// <seealso class='IDTExtensibility2' />
    public class Connect : IDTExtensibility2, IDTCommandTarget
    {
        /// <summary>アドイン オブジェクトのコンストラクタを実装します。初期化コードをこのメソッド内に配置してください。</summary>
        public Connect()
        {
        }

        #region Visual Studio で生成されたコード
        /// <summary>IDTExtensibility2 インターフェイスの OnConnection メソッドを実装します。アドインが読み込まれる際に通知を受けます。</summary>
        /// <param term='application'>ホスト アプリケーションのルート オブジェクトです。</param>
        /// <param term='connectMode'>アドインの読み込み状態を説明します。</param>
        /// <param term='addInInst'>このアドインを表すオブジェクトです。</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnConnection( object application, ext_ConnectMode connectMode, object addInInst, ref Array custom )
        {
            _applicationObject = (DTE2)application;
            _addInInstance = (AddIn)addInInst;
#if false
            Initialize();
#else
            if ( connectMode == ext_ConnectMode.ext_cm_UISetup ) {
                object[] contextGUIDS = new object[] { };
                Commands2 commands = (Commands2)_applicationObject.Commands;
                string toolsMenuName;

                try {
                    //コマンドを別のメニューに移動するには、単語 "Tools" を英語版のメニューに変換してください。 
                    //  このコードはカルチャを認識して、メニュー名に追加した後、コマンドをそのメニューに追加します。
                    //  ファイル内にトップレベル メニューの一覧があります。
                    //  CommandBar.resx.
                    string resourceName;
                    ResourceManager resourceManager = new ResourceManager( "VisualStudioTracAddIn.CommandBar", Assembly.GetExecutingAssembly() );
                    CultureInfo cultureInfo = new CultureInfo( _applicationObject.LocaleID );

                    if ( cultureInfo.TwoLetterISOLanguageName == "zh" ) {
                        System.Globalization.CultureInfo parentCultureInfo = cultureInfo.Parent;
                        resourceName = String.Concat( parentCultureInfo.Name, "Tools" );
                    }
                    else {
                        resourceName = String.Concat( cultureInfo.TwoLetterISOLanguageName, "Tools" );
                    }
                    toolsMenuName = resourceManager.GetString( resourceName );
                }
                catch {
                    //単語 'Tools' の他言語バージョンを検索しましたが、見つかりませんでした。
                    //  既定は en-US の単語ですが、現在のカルチャでも機能する可能性があります。
                    toolsMenuName = "Tools";
                }

                //コマンドを [ツール] メニューに配置します。
                //メイン メニュー項目のすべてを保持するトップレベル コマンド バーである、MenuBar コマンド バーを検索します:
                Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];

                //MenuBar コマンド バーで [ツール] コマンド バーを検索します:
                CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
                CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;

                //アドインによって処理する複数のコマンドを追加する場合、この try ブロックおよび catch ブロックを重複できます。
                //  ただし、新しいコマンド名を含めるために QueryStatus メソッドおよび Exec メソッドの更新も実行してください。
                try {
                    //コマンド コレクションにコマンドを追加します:
                    Command command = commands.AddNamedCommand2( _addInInstance,
                        "VisualStudioTracAddIn",
                        "Trac アドインの表示",
                        "Executes the command for VisualStudioTracAddIn",
                        true, 59, ref contextGUIDS,
                        (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled,
                        (int)vsCommandStyle.vsCommandStylePictAndText,
                        vsCommandControlType.vsCommandControlTypeButton );

                    //コマンドのコントロールを [ツール] メニューに追加します:
                    if ( (command != null) && (toolsPopup != null) ) {
                        object ret = command.AddControl( toolsPopup.CommandBar, 1 );
                    }
                }
                catch ( System.ArgumentException ) {
                    //同じ名前のコマンドが既に存在しているため、例外が発生した可能性があります。
                    //  その場合、コマンドを再作成する必要はありません。 例外を 
                    //  無視しても安全です。
                }
            }
#endif
        }

        /// <summary>IDTExtensibility2 インターフェイスの OnDisconnection メソッドを実装します。アドインがアンロードされる際に通知を受けます。</summary>
        /// <param term='disconnectMode'>アドインのアンロード状態を説明します。</param>
        /// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnDisconnection( ext_DisconnectMode disconnectMode, ref Array custom )
        {
            Deinitialize();
        }

        /// <summary>IDTExtensibility2 インターフェイスの OnAddInsUpdate メソッドを実装します。アドインのコレクションが変更されたときに通知を受けます。</summary>
        /// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
        /// <seealso class='IDTExtensibility2' />		
        public void OnAddInsUpdate( ref Array custom )
        {
        }

        /// <summary>IDTExtensibility2 インターフェイスの OnStartupComplete メソッドを実装します。ホスト アプリケーションが読み込みを終了したときに通知を受けます。</summary>
        /// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnStartupComplete( ref Array custom )
        {
        }

        /// <summary>IDTExtensibility2 インターフェイスの OnBeginShutdown メソッドを実装します。ホスト アプリケーションがアンロードされる際に通知を受けます。</summary>
        /// <param term='custom'>ホスト アプリケーション固有のパラメータの配列です。</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnBeginShutdown( ref Array custom )
        {
        }

        /// <summary>IDTCommandTarget インターフェイスの QueryStatus メソッドを実装します。これは、コマンドの可用性が更新されたときに呼び出されます。</summary>
        /// <param term='commandName'>状態を決定するためのコマンド名です。</param>
        /// <param term='neededText'>コマンドに必要なテキストです。</param>
        /// <param term='status'>ユーザー インターフェイス内のコマンドの状態です。</param>
        /// <param term='commandText'>neededText パラメータから要求されたテキストです。</param>
        /// <seealso class='Exec' />
        public void QueryStatus( string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText )
        {
            if ( neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone ) {
                if ( commandName == "VisualStudioTracAddIn.Connect.VisualStudioTracAddIn" ) {
                    status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
                    return;
                }
            }
        }

        /// <summary>IDTCommandTarget インターフェイスの Exec メソッドを実装します。これは、コマンドが実行されるときに呼び出されます。</summary>
        /// <param term='commandName'>実行するコマンド名です。</param>
        /// <param term='executeOption'>コマンドの実行方法を説明します。</param>
        /// <param term='varIn'>呼び出し元からコマンド ハンドラへ渡されたパラメータです。</param>
        /// <param term='varOut'>コマンド ハンドラから呼び出し元へ渡されたパラメータです。</param>
        /// <param term='handled'>コマンドが処理されたかどうかを呼び出し元に通知します。</param>
        /// <seealso class='Exec' />
        public void Exec( string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled )
        {
            handled = false;
            if ( executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault ) {
                if ( commandName == "VisualStudioTracAddIn.Connect.VisualStudioTracAddIn" ) {
                    Initialize();
                    handled = true;
                    return;
                }
            }
        }
        private DTE2 _applicationObject;
        private AddIn _addInInstance;
        #endregion

        /// <summary>
        /// フォーム
        /// </summary>
        private FormTracAddIn formAddIn = null;
        private Window window = null;
        private _dispSolutionEvents_OpenedEventHandler OpenedEventHandler = null;

        /// <summary>
        /// 初期化
        /// </summary>
        private void Initialize()
        {
            try {
                if ( (formAddIn == null) && (window == null) ) {
                    Deinitialize();

                    Windows2 windows = this._addInInstance.DTE.Windows as Windows2;
                    if ( windows != null ) {
                        Assembly thisAssembly = Assembly.GetAssembly( this.GetType() );
                        object controlObject = null;
                        window = windows.CreateToolWindow2( this._addInInstance, thisAssembly.Location,
                                                                    "VisualStudioTracAddIn.FormTracAddIn", "Trac",
                                                                    "{B83C10F9-6D33-4c71-91F9-9DF34F94C9FE}",
                                                                    ref controlObject );
                        if ( window != null ) {
                            // フォームの設定
                            formAddIn = (FormTracAddIn)controlObject;
                            formAddIn.ApplicationObject = _applicationObject;

                            OpenedEventHandler = new _dispSolutionEvents_OpenedEventHandler( SolutionEvents_Opened );
                            _applicationObject.Events.SolutionEvents.Opened += OpenedEventHandler;


                            window.Visible = true;
                        }
                    }
                }
                else {
                    window.Visible = true;
                }
            }
            catch ( Exception ex ) {
                MessageBox.Show( ex.Message, _addInInstance.Name, MessageBoxButtons.OK, MessageBoxIcon.Error );
            }
        }

        /// <summary>
        /// 削除処理を追加
        /// </summary>
        private void Deinitialize()
        {
            if ( OpenedEventHandler != null ) {
                _applicationObject.Events.SolutionEvents.Opened -= OpenedEventHandler;
                OpenedEventHandler = null;
            }

            formAddIn = null;
            window = null;

            GC.Collect();
        }

        /// <summary>
        /// ソリューションのオープン
        /// </summary>
        void SolutionEvents_Opened()
        {
            Solution sln = _applicationObject.Solution;
            if ( string.IsNullOrEmpty( sln.FullName ) ) {
                return;
            }

            // ファイル名からソリューションを取得
            string SolutionName = Path.GetFileNameWithoutExtension( sln.FullName );
            MessageBox.Show( SolutionName );
        }
    }
}