using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using pcmp.Setting;
using System.Diagnostics;
using System.IO;
using System.Media;
using System.Threading;
using System.Reflection;
using System.Net;
using KaoriYa.Migemo;
using System.Text.RegularExpressions;

namespace pcmp.Forms
{
    public partial class FormMain : Form
    {
        FormWindowState _state = FormWindowState.Normal;
        bool ShutdownFlag = false;
        System.Threading.Timer checkMessageQueueTimer = null;
        public static BalloonMessageManager MessageManager = new BalloonMessageManager();
        bool _balloonShowing;
        // SoundPlayer sp = new SoundPlayer();
        Migemo migemo = null;
        public static HostScript HostScript;

        private FormChannelList formChannelList;
        private FormYpInfo formYpInfo;
        private FormPeCaInfo formPeCaInfo;
        private FormChannelInfo formChannelInfo;
        private FormLogging formLogging;
        private FormShowFavorite formShowFav;

        public FormMain()
        {
            InitializeComponent();

            // ログ表示用のフォームを初期化
            formLogging = new FormLogging();

            SetWindowText();

            // 設定の読み込み
            Setting.Settings.LoadYpSetting();
            Setting.Settings.LoadFavSetting();
            Setting.Settings.LoadNGSetting();
            Setting.Settings.LoadGeneralSetting();
            Setting.Settings.LoadPlayerSetting();

            // プロセス優先度の設定
            ChangeProcessPriority();

            // 各フォームの初期化
            formChannelList = new FormChannelList();
            formChannelInfo = new FormChannelInfo();
            formYpInfo = new FormYpInfo();
            formPeCaInfo = new FormPeCaInfo();
            formShowFav = new FormShowFavorite(formChannelList);

            // メッセージタイマーの初期化
            checkMessageQueueTimer = new System.Threading.Timer(CheckMessageQueue);

            // イベントの登録
            Application.Idle += new EventHandler(Application_Idle);
            ChannelRefreshThread.RefreshChannelsCompleteEvent += new RefreshChannelCompleteEventHandler(ChannelRefreshThread_RefreshChannelsCompleteEvent);
            formChannelList.OnListViewSelectedIndexChanged += new EventHandler(formChannelList_OnListViewSelectedIndexChanged);
            formChannelList.OnChangeLisRelStat += new ChangeListnerRelayStatEventHandler(formChannelList_OnChangeLisRelStat);
            formChannelList.OnNavigateUrl += new NavigateUrlEventHandler(formChannelList_OnNavigateUrl);
            formChannelInfo.OnNewWindow += new EventHandler<ThrowUrlEventArgs>(formChannelInfo_OnNewWindow);
            formChannelInfo.OnPlayChannel += new EventHandler<ThrowUrlEventArgs>(formChannelInfo_OnPlayChannel);
            formYpInfo.RefreshIndexTxtStream += new EventHandler(formYpInfo_RefreshIndexTxtStream);
        }

        void formChannelInfo_OnPlayChannel(object sender, ThrowUrlEventArgs e)
        {
            formChannelList.PlayChannel(e.Channel);
        }

        void formChannelInfo_OnNewWindow(object sender, ThrowUrlEventArgs e)
        {
            ShowBrowser(e.Url);
        }

        void ShowBrowser(string url)
        {
            FormBrowser browser = new FormBrowser();
            browser.Show(formChannelList.Pane, null);
            browser.NavigateUrl(url);
        }

        void ShowBrowser()
        {
            ShowBrowser(string.Empty);
        }

        void formChannelList_OnNavigateUrl(string url)
        {
            ShowBrowser(url);
        }

        private void SetWindowText()
        {
            this.Text = "pcmp " + Assembly.GetExecutingAssembly().GetName().Version.ToString();
        }

        void formChannelList_OnChangeLisRelStat(int ch, int lis, int rel)
        {
            toolStripStatusLabelStatus.Text = string.Format("{0} ch. / {1} lis. / {2} rel.",
                ch, lis, rel);
        }

        void formYpInfo_RefreshIndexTxtStream(object sender, EventArgs e)
        {
            // GUIを操作する前にInvoke必要
            while (ChannelRefreshThread.IsBusy) Thread.Sleep(100);
            this.Invoke(new MethodInvoker(delegate
            {
                toolStripButtonRefrsh.Enabled = false;
                menuItemYP.Enabled = false;
                formYpInfo.tabControl.Enabled = false;
            }));
            // ChannelRefreshThread.source = IndexTextSource.PCRaw;
            ChannelRefreshThread.StartRefreshChannels((YpSetting[])sender);
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case (int)WindowsMessages.WM_QUERYENDSESSION:
                    // シャットダウン時に終了する
                    ShutdownFlag = true;
                    checkMessageQueueTimer.Change(-1, 0);
                    checkMessageQueueTimer.Dispose();
                    checkMessageQueueTimer = null;
                    break;

                case (int)WindowsMessages.WM_COPYDATA:
                    // コマンドのチェック
                    Win32.COPYDATASTRUCT cdStruct = (Win32.COPYDATASTRUCT)m.GetLParam(typeof(Win32.COPYDATASTRUCT));
                    string cmd = cdStruct.lpData;
                    ProcessCommand(cmd);
                    break;
            }

            base.WndProc(ref m);
        }

        private void ProcessCommand(string cmd)
        {
            switch (cmd)
            {
                case Common.CommandActivate:
                    // ウィンドウを元に戻す
                    RestoreWindow();
                    break;
            }
        }

        void RestoreWindow()
        {
            //if (WindowState == FormWindowState.Minimized)
            //{
            // フォームを表示可能にする
            Visible = true;

            // ウィンドウの状態を戻す(通常/最大化)
            WindowState = _state;
            //}

            // スレッドのIDを取得する
            int fore_thread = Win32.GetWindowThreadProcessId(Win32.GetForegroundWindow(), IntPtr.Zero);
            int this_thread = Win32.GetCurrentThreadId();
            // Thread のアタッチ
            Win32.AttachThreadInput(this_thread, fore_thread, true);

            // this をアクティブ
            Activate();

            // Thread のデタッチ
            Win32.AttachThreadInput(this_thread, fore_thread, false);
        }

        void formChannelList_OnListViewSelectedIndexChanged(object sender, EventArgs e)
        {
            ListView listView = (ListView)sender;
            if (listView.SelectedItems.Count == 0)
            {
                toolStripButtonPlayChannel.Enabled = false;
                toolStripButtonAddFav.Enabled = false;
                return;
            }
            ListViewItem item = listView.SelectedItems[0];
            formChannelInfo.ShowChannelInfo(item);
            toolStripButtonPlayChannel.Enabled = true;
            toolStripButtonAddFav.Enabled = true;
        }

        void Application_Idle(object sender, EventArgs e)
        {
            Application.Idle -= new EventHandler(Application_Idle);

            RefreshToolStripButton();
            RefreshMenuItem();
            RefreshExtToolItem();

            HostScript = new HostScript();

            string migemodictpath = Path.Combine(Application.StartupPath, "dict\\migemo-dict");
            if (Migemo.Available())
            {
                migemo = new Migemo(migemodictpath);
                Trace.WriteLine("Migemo検出");
                Trace.WriteLine("インクリメンタルサーチにMigemoを使用します");
            }

            if (migemo != null && migemo.IsEnable())
                toolStripSearchComboBox.KeyUp += new KeyEventHandler(toolStripSearchComboBox_KeyUp_Migemo);
            else toolStripSearchComboBox.KeyUp += new KeyEventHandler(toolStripSearchComboBox_KeyUp);
        }

        private void RefreshExtToolItem()
        {
            ToolSetting[] toolsettings = Setting.ToolSetting.Load();
            if (toolsettings != null)
            {
                menuItemExtTool.DropDownItems.Clear();
                foreach (ToolSetting item in toolsettings)
                {
                    ToolStripMenuItem menu = new ToolStripMenuItem();
                    menu.Text = item.Name;
                    menu.Tag = item;
                    menu.Click += new EventHandler(ExternalToolMenuItem_Click);
                    menuItemExtTool.DropDownItems.Add(menu);
                }
            }
        }

        void ExternalToolMenuItem_Click(object sender, EventArgs e)
        {
            if (formChannelList.listViewChannels.SelectedItems.Count == 0) return;
            ToolSetting tool = (ToolSetting)((ToolStripMenuItem)sender).Tag;
            Channel selItem = formChannelList.listViewChannels.SelectedItems[0].Tag as Channel;
            switch (tool.Type)
            {
                case 0:
                    // 実行可能ファイル
                    string arg = tool.Argument;
                    arg = Common.ReplaceTag(arg, selItem);
                    //arg = arg.Replace("<channelname />", Common.ToArg(selItem.ChannelName));
                    //arg = arg.Replace("<stream />", Common.ToArg(selItem.StreamUrl));

                    if (arg.Contains("<stream_audio />"))
                    {
                        HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(selItem.StreamUrl);
                        RequestState reqestState = new RequestState();
                        reqestState.argument = arg;
                        reqestState.request = webReq;
                        reqestState.path = tool.Path;
                        try
                        {
                            webReq.BeginGetResponse(new AsyncCallback(formChannelList.GetAudioStreamUrl), reqestState);
                        }
                        catch (WebException) { }
                        catch { }

                        return;
                    }

                    Common.StartProcess(tool.Path, arg);
                    break;
                case 1:
                    // Pythonスクリプト
                    if (HostScript.EnableScript)
                    {
                        HostScript.AddGlobal("Channel", selItem);
                        HostScript.AddGlobal("YpSetting", Settings.FindYpSetting(selItem.YPName));
                        if (selItem.FavIndex != -1)
                            HostScript.AddGlobal("FavSetting", Settings.FavSettings[selItem.FavIndex]);
                        else HostScript.AddGlobal("FavSetting", null);
                        HostScript.AddGlobal("FavSettings", Settings.FavSettings);
                        HostScript.AddGlobal("GeneralSetting", Settings.GeneralSetting);
                        HostScript.AddGlobal("PlayerSettings", Settings.PlayerSettings);

                        HostScript.ExecuteFile(tool.Path);
                    }
                    break;
            }
        }

        void item_pcraw_Click(object sender, EventArgs e)
        {
            // PCRawから更新
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            if (item == null) return;
            YpSetting yp = item.Tag as YpSetting;
            if (yp == null) return;

            YpSetting[] yparray = { yp };
            yp.Source = IndexTextSource.PCRaw;
            if (ChannelRefreshThread.IsBusy) return;
            toolStripButtonRefrsh.Enabled = false;
            menuItemYP.Enabled = false;
            formYpInfo.tabControl.Enabled = false;
            // ChannelRefreshThread.source = IndexTextSource.PCRaw;
            ChannelRefreshThread.StartRefreshChannels(yparray);
        }

        void item_http_Click(object sender, EventArgs e)
        {
            // Httpから更新
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            if (item == null) return;
            YpSetting yp = item.Tag as YpSetting;
            if (yp == null) return;
            yp.Source = IndexTextSource.Http;

            if ((DateTime.Now - yp.LastHttpAccess).TotalSeconds < 60)
            {
                ShowStatusMessage(string.Format("{0}は前回更新より60秒たっていません。更新を中止します。", yp.YpName),
                    Color.Red);
                return;
            }
            else
            {
                ShowStatusMessage("更新開始");
            }
            YpSetting[] yparray = { yp };
            if (ChannelRefreshThread.IsBusy) return;
            toolStripButtonRefrsh.Enabled = false;
            menuItemYP.Enabled = false;
            formYpInfo.tabControl.Enabled = false;
            // ChannelRefreshThread.source = IndexTextSource.Http;
            ChannelRefreshThread.StartRefreshChannels(yparray);
        }

        void item_openbrowser_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            if (item == null) return;
            YpSetting yp = item.Tag as YpSetting;
            if (yp == null) return;

            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, yp.YpAddr);
                return;
            }

            RestoreWindow();
            ShowBrowser(yp.YpAddr);
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            Settings.LoadApplicationSetting();
            if (Settings.ApplicationSetting != null)
            {
                StartPosition = FormStartPosition.Manual;
                Size = new Size(Settings.ApplicationSetting.WindowWidth, Settings.ApplicationSetting.WindowHeight);
                Location = new Point(Settings.ApplicationSetting.WindowPosX, Settings.ApplicationSetting.WindowPosY);
                WindowState = Settings.ApplicationSetting.WindowState;
                dockPanel1.DockTopPortion = Settings.ApplicationSetting.DockTopPortion;
                dockPanel1.DockBottomPortion = Settings.ApplicationSetting.DockBottomPortion;
                dockPanel1.DockRightPortion = Settings.ApplicationSetting.DockRightPortion;
                dockPanel1.DockLeftPortion = Settings.ApplicationSetting.DockLeftPortion;

                if (Settings.ApplicationSetting.DockState != DockState.Unknown)
                    formChannelInfo.Show(dockPanel1, Settings.ApplicationSetting.DockState);
                else formChannelInfo.Show(dockPanel1, DockState.DockBottom);
            }
            else
            {
                formChannelInfo.Show(dockPanel1, DockState.DockBottom);
            }

            // PeerCastの起動
            if (Settings.GeneralSetting.RunPeerCastOnStartup)
                PeerCast.StartPeerCast();

            formChannelList.Show(dockPanel1, DockState.Document);
            formYpInfo.Show(formChannelList.Pane, null);
            formPeCaInfo.Show(formChannelList.Pane, null);
            formLogging.Show(formChannelList.Pane, null);
            formChannelList.Pane.ActiveContent = formChannelList;

            checkMessageQueueTimer.Change(0, 500);
        }

        void ChangeProcessPriority()
        {
            if (Settings.GeneralSetting == null) return;
            if (!Settings.GeneralSetting.ChangeProcessPriority) return;
            // 0:High 1:AboveNormal 2:Normal 3:BelowNormal 4:Idle
            ProcessPriorityClass ppc;
            switch (Settings.GeneralSetting.ProcessPriority)
            {
                case 0: ppc = ProcessPriorityClass.High; break;
                case 1: ppc = ProcessPriorityClass.AboveNormal; break;
                case 2: ppc = ProcessPriorityClass.Normal; break;
                case 3: ppc = ProcessPriorityClass.BelowNormal; break;
                case 4: ppc = ProcessPriorityClass.Idle; break;
                default: ppc = ProcessPriorityClass.Normal; break;
            }
            Process p = Process.GetCurrentProcess();
            p.PriorityClass = ppc;
        }

        private void RefreshToolStripButton()
        {
            toolStripButtonRefrsh.DropDownItems.Clear();

            if (Settings.YpSettings != null)
            {
                ToolStripMenuItem[] items = new ToolStripMenuItem[Settings.YpSettings.Length];
                for (int i = 0; i < Settings.YpSettings.Length; i++)
                {
                    ToolStripMenuItem item = new ToolStripMenuItem();
                    item.Text = Settings.YpSettings[i].YpName;
                    item.Tag = Settings.YpSettings[i];
                    item.Click += new EventHandler(ClickYpRefrshItem);
                    ToolStripMenuItem item_http = new ToolStripMenuItem();
                    item_http.Text = "イエローページから取得";
                    item_http.Tag = item.Tag;
                    item_http.Click += new EventHandler(item_http_Click);
                    item.DropDownItems.Add(item_http);
                    ToolStripMenuItem item_pcraw = new ToolStripMenuItem();
                    item_pcraw.Text = "PCRawから取得";
                    item_pcraw.Tag = item.Tag;
                    item_pcraw.Enabled = Settings.YpSettings[i].HaveIndexTextStream;
                    item_pcraw.Click += new EventHandler(item_pcraw_Click);
                    item.DropDownItems.Add(item_pcraw);
                    items[i] = item;
                }
                toolStripButtonRefrsh.DropDownItems.AddRange(items);
            }
            else
            {
                toolStripButtonRefrsh.Enabled = false;
            }
        }

        private void RefreshMenuItem()
        {
            menuItemYP.DropDownItems.Clear();

            if (Settings.YpSettings != null)
            {
                ToolStripMenuItem[] items = new ToolStripMenuItem[Settings.YpSettings.Length];
                ToolStripMenuItem itemallref = new ToolStripMenuItem();
                itemallref.Text = "すべて更新";
                itemallref.Click += new EventHandler(allYpRefreshClick);
                ToolStripSeparator sep = new ToolStripSeparator();
                menuItemYP.DropDownItems.Add(itemallref);
                menuItemYP.DropDownItems.Add(sep);

                for (int i = 0; i < Settings.YpSettings.Length; i++)
                {
                    ToolStripMenuItem item = new ToolStripMenuItem();
                    item.Text = Settings.YpSettings[i].YpName;
                    item.Tag = Settings.YpSettings[i];
                    item.Click += new EventHandler(ClickYpRefrshItem);
                    ToolStripMenuItem item_http = new ToolStripMenuItem();
                    item_http.Text = "イエローページから取得";
                    item_http.Tag = item.Tag;
                    item_http.Click += new EventHandler(item_http_Click);
                    item.DropDownItems.Add(item_http);
                    ToolStripMenuItem item_pcraw = new ToolStripMenuItem();
                    item_pcraw.Text = "PCRawから取得";
                    item_pcraw.Tag = item.Tag;
                    item_pcraw.Enabled = Settings.YpSettings[i].HaveIndexTextStream;
                    item_pcraw.Click += new EventHandler(item_pcraw_Click);
                    item.DropDownItems.Add(item_pcraw);
                    ToolStripSeparator item_sep = new ToolStripSeparator();
                    item.DropDownItems.Add(item_sep);
                    ToolStripMenuItem item_openbrowser = new ToolStripMenuItem();
                    item_openbrowser.Text = "ブラウザで開く";
                    item_openbrowser.Tag = item.Tag;
                    item_openbrowser.Click += new EventHandler(item_openbrowser_Click);
                    item.DropDownItems.Add(item_openbrowser);
                    ToolStripMenuItem item_checkbandwidth = new ToolStripMenuItem();
                    item_checkbandwidth.Text = "帯域を測定する";
                    item_checkbandwidth.Enabled = Settings.YpSettings[i].UseBandwidthTool;
                    item_checkbandwidth.Tag = item.Tag;
                    item_checkbandwidth.Click += new EventHandler(item_checkbandwidth_Click);
                    item.DropDownItems.Add(item_checkbandwidth);
                    items[i] = item;
                }
                menuItemYP.DropDownItems.AddRange(items);
            }
            else
            {
                toolStripButtonRefrsh.Enabled = false;
            }
        }

        void item_checkbandwidth_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            if (item == null) return;
            YpSetting yp = item.Tag as YpSetting;
            if (yp == null) return;

            Common.StartProcess(yp.BandwidthToolPath, Common.ReplaceTag(yp.BandwidthToolArg, yp));
        }

        void allYpRefreshClick(object sender, EventArgs e)
        {
            RefreshAllYp();
        }

        void ClickYpRefrshItem(object sender, EventArgs e)
        {
            ToolStripMenuItem item = sender as ToolStripMenuItem;
            if (item == null) return;
            YpSetting yp = item.Tag as YpSetting;
            if (yp == null) return;
            yp.Source = IndexTextSource.Both;

            if ((DateTime.Now - yp.LastHttpAccess).TotalSeconds < 60)
            {
                if (!yp.HaveIndexTextStream)
                {
                    ShowStatusMessage(string.Format("{0}は前回更新より60秒たっていません。更新を中止します。", yp.YpName),
                        Color.Red);
                    return;
                }
                else
                {
                    ShowStatusMessage(string.Format("{0}はPCRawからのみ取得試行します。", yp.YpName));
                    yp.Source = IndexTextSource.PCRaw;
                }
            }
            else
            {
                ShowStatusMessage("更新開始");
            }
            YpSetting[] yparray = { yp };
            if (ChannelRefreshThread.IsBusy) return;
            toolStripButtonRefrsh.Enabled = false;
            menuItemYP.Enabled = false;
            formYpInfo.tabControl.Enabled = false;
            // ChannelRefreshThread.source = IndexTextSource.Both;
            ChannelRefreshThread.StartRefreshChannels(yparray);
        }

        private void toolStripButtonRefrsh_ButtonClick(object sender, EventArgs e)
        {
            RefreshAllYp();
        }

        void RefreshAllYp()
        {
            Trace.WriteLine("YPの更新開始(すべてのYP)");

            if (ChannelRefreshThread.IsBusy) return;
            toolStripButtonRefrsh.Enabled = false;
            menuItemYP.Enabled = false;
            string ypstr = string.Empty;
            List<YpSetting> yps = new List<YpSetting>();
            foreach (YpSetting yp in Settings.YpSettings)
            {
                if ((DateTime.Now - yp.LastHttpAccess).TotalSeconds < 60)
                {
                    if (!yp.HaveIndexTextStream) ypstr += yp.YpName + "/";
                    else
                    {
                        yp.Source = IndexTextSource.PCRaw;
                        yps.Add(yp);
                    }
                }
                else
                {
                    yp.Source = IndexTextSource.Both;
                    yps.Add(yp);
                }
            }
            if (ypstr.Length != 0)
            {
                Trace.WriteLine(ypstr.Remove(ypstr.Length - 1) + "はHTTP60秒制限により更新されません。");
                // ShowStatusMessage(ypstr.Remove(ypstr.Length - 1) + "はHTTP60秒制限により更新されません。", Color.Red);
            }
            else
            {
                ShowStatusMessage("更新開始");
            }

            // ChannelRefreshThread.source = IndexTextSource.Both;
            ChannelRefreshThread.StartRefreshChannels(yps.ToArray());
        }

        void ChannelRefreshThread_RefreshChannelsCompleteEvent(string msg)
        {
            ProcessChannels();
            formYpInfo.RefreshDisplayValue();
            formChannelList.RefreshDisplayChannels();
            RefreshMenuItem();
            RefreshToolStripButton();
            toolStripButtonRefrsh.Enabled = true;
            menuItemYP.Enabled = true;
            formYpInfo.tabControl.Enabled = true;
            ShowStatusMessage(string.Format("更新完了({0})", DateTime.Now.ToLongTimeString()));

            // バルーンで通知
            if (Settings.GeneralSetting.ShowYpBalloon)
            {
                notifyIcon1.BalloonTipTitle = "YP更新完了";
                notifyIcon1.BalloonTipText = msg.Remove(msg.Length - 2);
                notifyIcon1.ShowBalloonTip(5000);
                _balloonShowing = true;
            }

            // checkMessageQueueTimer.Change(0, 500);
        }

        private void ProcessChannels()
        {
            List<Channel> newfavlist = new List<Channel>();

            foreach (YpSetting yp in Settings.YpSettings)
            {
                foreach (Channel channel in yp.Channels)
                {
                    NGSetting ng = channel.MatchNG(Settings.NGSettings);
                    FavSetting fav = null;
                    if (ng == null) fav = channel.MatchFav(Settings.FavSettings);
                    if (channel.Diff == ChannelDiff.New && channel.MatchStatus == MatchStatus.Favorite)
                    {
                        newfavlist.Add(channel);
                    }

                    channel.DispStyle.TextColor = yp.TextColor;
                    channel.DispStyle.BackColor = yp.BackColor;
                    channel.DispStyle.Font = yp.Font;
                    channel.DispStyle.ContactColor = yp.ContactColor;
                    channel.DispStyle.ContactStyle = yp.ContactFontStyle;
                    channel.DispStyle.DirectColor = yp.DirectColor;
                    channel.DispStyle.DirectStyle = yp.DirectFontStyle;
                    if (fav != null && fav.UseColorSetting)
                    {
                        channel.DispStyle.TextColor = fav.TextColor;
                        channel.DispStyle.BackColor = fav.BackColor;
                        channel.DispStyle.ContactColor = fav.TextColor;
                        channel.DispStyle.DirectColor = fav.TextColor;
                        channel.DispStyle.Font = fav.Font;
                    }
                }
            }

            formShowFav.ShowFavorites(newfavlist);
        }

        private void FormMain_Resize(object sender, EventArgs e)
        {
            // 最小化された場合、タスクバーから消す
            if (WindowState == FormWindowState.Minimized)
            {
                if (Settings.GeneralSetting.HideOnMinimize)
                {
                    Application.DoEvents();
                    Visible = false;
                }
            }
            else _state = WindowState;
        }

        private void FormMain_Shown(object sender, EventArgs e)
        {
            // 起動時に最小化
            if (Settings.GeneralSetting.RunAsMinimize)
            {
                WindowState = FormWindowState.Minimized;
            }
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result;
            if (Settings.GeneralSetting.ShowExitDialog && !ShutdownFlag)
            {
                result = MessageBox.Show("pcmpを終了しますか？", "PeerCastMultiPlayer2", MessageBoxButtons.YesNo,
                MessageBoxIcon.Question);
            }
            else
            {
                result = DialogResult.Yes;
            }

            if (result != DialogResult.Yes)
            {
                e.Cancel = true;
                return;
            }

            // PeerCastを終了する場合終了処理
            if (Settings.GeneralSetting.ClosePeerCastOnExit && !ShutdownFlag)
            {
                if (MessageBox.Show("PeerCastを終了しますか？", "PCMP2", MessageBoxButtons.YesNo)
                    == DialogResult.Yes)
                {
                    PeerCast.KillPeerCast(Settings.GeneralSetting.PeerCastPath);
                }
            }

            // Yesがクリックされたとき
            if (Settings.ApplicationSetting == null)
                Settings.ApplicationSetting = new ApplicationSetting();
            // Formのサイズ、位置、状態
            if (WindowState != FormWindowState.Normal)
            {
                Settings.ApplicationSetting.WindowHeight = RestoreBounds.Height;
                Settings.ApplicationSetting.WindowWidth = RestoreBounds.Width;
                Settings.ApplicationSetting.WindowPosX = RestoreBounds.Location.X;
                Settings.ApplicationSetting.WindowPosY = RestoreBounds.Location.Y;
                Settings.ApplicationSetting.WindowState = _state;
            }
            else
            {
                Settings.ApplicationSetting.WindowHeight = Height;
                Settings.ApplicationSetting.WindowWidth = Width;
                Settings.ApplicationSetting.WindowPosX = Location.X;
                Settings.ApplicationSetting.WindowPosY = Location.Y;
                Settings.ApplicationSetting.WindowState = FormWindowState.Normal;
            }
            // ドッキングウィンドウのサイズの保存
            Settings.ApplicationSetting.DockTopPortion = dockPanel1.DockTopPortion;
            Settings.ApplicationSetting.DockBottomPortion = dockPanel1.DockBottomPortion;
            Settings.ApplicationSetting.DockRightPortion = dockPanel1.DockRightPortion;
            Settings.ApplicationSetting.DockLeftPortion = dockPanel1.DockLeftPortion;
            // 保存
            Settings.ApplicationSetting.Save();
            Application.DoEvents();

            // トレイアイコンを非表示にする
            notifyIcon1.Visible = false;

            // すべてのウィンドウを閉じる
            IDockContent[] documents = dockPanel1.DocumentsToArray();
            foreach (IDockContent content in documents)
                content.DockHandler.Close();

            // キューをすべて処理する
            Application.DoEvents();
            // アプリケーションの終了
            Application.ExitThread();
        }

        private void CheckMessageQueue(object state)
        {
            if (MessageManager.Queue.Count == 0)
            {
                checkMessageQueueTimer.Change(-1, 500);
                return;
            }
            if (_balloonShowing) return;

            BalloonMessageItem item;
            item = MessageManager.Queue.Dequeue();
            string title = item.Title;
            notifyIcon1.BalloonTipText = item.Text;
            if (title != "新着お気に入り")
            {
                if (Settings.GeneralSetting.ShowNewBalloon)
                {
                    List<BalloonMessageItem> notifyItems = new List<BalloonMessageItem>();
                    notifyItems.Add(item);
                    if (MessageManager.Queue.Count != 0 &&
                        MessageManager.Queue.Peek().Title == title)
                    {
                        item = MessageManager.Queue.Dequeue();
                        notifyIcon1.BalloonTipText += "\n" + item.Text;
                    }
                    if (MessageManager.Queue.Count != 0 &&
                        MessageManager.Queue.Peek().Title == title)
                    {
                        item = MessageManager.Queue.Dequeue();
                        notifyIcon1.BalloonTipText += "\n" + item.Text;
                    }
                    notifyIcon1.BalloonTipTitle = item.Title;
                    notifyIcon1.ShowBalloonTip(5000);
                    notifyIcon1.Tag = null;
                    _balloonShowing = true;
                }
            }
            else
            {
                //if (Settings.GeneralSetting.ShowFavoriteBalloon)
                //{
                //    if (File.Exists(item.Sound))
                //    {
                //        sp.SoundLocation = item.Sound;
                //        try
                //        {
                //            sp.Play();
                //        }
                //        catch { }
                //    }

                //    if (Settings.FavSettings[item.Channel.FavIndex].ShowBalloon)
                //    {
                //        notifyIcon1.BalloonTipTitle = item.Title;
                //        notifyIcon1.ShowBalloonTip(5000);
                //        notifyIcon1.Tag = item.Channel;

                //        _balloonShowing = true;
                //    }
                //}
            }
        }

        private void menuItemExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void menuItemGeneralSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormSetting formSetting = new FormSetting();
            if (formSetting.ShowDialog() == DialogResult.OK)
            {
                ApplySetting();
            }
            formSetting.Dispose();
        }

        private void ApplySetting()
        {
            formChannelList.ApplySetting();
            formChannelList.RefreshDisplayChannels();
            formChannelInfo.ApplySetting();
            formPeCaInfo.ApplySetting();
            formYpInfo.ApplySetting();

            RefreshMenuItem();
            RefreshToolStripButton();
            RefreshExtToolItem();
            ChangeProcessPriority();
        }

        private void menuItemYPSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormYpSetting formyp = new FormYpSetting();
            if (Settings.YpSettings != null)
            {
                foreach (YpSetting yp in Settings.YpSettings)
                {
                    if (yp.PCRawHandle != IntPtr.Zero)
                    {
                        Trace.WriteLine(string.Format("YP設定変更のため、PCRawハンドルをクローズします({0})", yp.YpName));
                        PCRaw.PCRawClose(yp.PCRawHandle);
                        yp.PCRawHandle = IntPtr.Zero;
                        formYpInfo.StopCheckPCRawThread();
                    }
                }
            }

            if (formyp.ShowDialog() == DialogResult.OK)
            {
                ApplySetting();
            }
            formyp.Dispose();
            formYpInfo.CreateCheckPCRawThread();
        }

        private void menuItemFavSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormFavSetting formfav = new FormFavSetting();
            if (formfav.ShowDialog() == DialogResult.OK)
            {
                ApplySetting();
            }
            formfav.Dispose();
        }

        private void menuItemPlayerSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormPlayerSetting formplay = new FormPlayerSetting();
            if (formplay.ShowDialog() == DialogResult.OK)
            {
                ApplySetting();
            }
            formplay.Dispose();
        }

        private void menuItemTabSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormTabSetting formtab = new FormTabSetting();
            if (formtab.ShowDialog() == DialogResult.OK)
            {
                ApplySetting();
            }
            formtab.Dispose();
        }

        private void menuItemShowVersion_Click(object sender, EventArgs e)
        {
            AboutBox about = new AboutBox();
            about.ShowDialog();
            about.Dispose();
        }

        private void toolStripButtonAutoRef_Click(object sender, EventArgs e)
        {
            if (toolStripButtonAutoRef.Checked)
            {
                toolStripComboBoxRefSpan.Enabled = false;
                // タイマーのインターバルを設定
                timerAutoRefresh.Interval = int.Parse(toolStripComboBoxRefSpan.Text) * 60 * 1000;
                timerAutoRefresh.Start();
            }
            else
            {
                toolStripComboBoxRefSpan.Enabled = true;
                timerAutoRefresh.Stop();
            }
        }

        private void toolStripComboBoxRefSpan_TextChanged(object sender, EventArgs e)
        {
            int time;

            if (toolStripComboBoxRefSpan.Text == "")
            {
                // 更新時間が空の時
                // 自動更新ボタンを無効にする
                toolStripButtonAutoRef.Enabled = false;
                return;
            }
            if (int.TryParse(toolStripComboBoxRefSpan.Text, out time))
            {
                if (time < 10)
                {
                    // 更新時間が10分以下の時
                    // 自動更新ボタンを無効にする
                    toolStripButtonAutoRef.Enabled = false;
                    return;
                }
                else
                {
                    toolStripButtonAutoRef.Enabled = true;
                }
            }
            else
            {
                // 入力された時間がint型に変換できなかったとき
                toolStripButtonAutoRef.Enabled = false;
            }
        }

        private void timerAutoRefresh_Tick(object sender, EventArgs e)
        {
            RefreshAllYp();
        }

        public void ShowStatusMessage(string text)
        {
            toolStripStatusLabel1.Text = text;
            toolStripStatusLabel1.ForeColor = Color.Black;
        }

        public void ShowStatusMessage(string text, Color color)
        {
            toolStripStatusLabel1.Text = text;
            toolStripStatusLabel1.ForeColor = color;
        }

        private void toolStripButtonSearch_Click(object sender, EventArgs e)
        {
            formChannelList.SearchChannel(toolStripSearchComboBox.Text);
        }

        private void toolStripSearchComboBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                e.SuppressKeyPress = true;
                toolStripButtonSearch.PerformClick();
            }
        }

        private void toolStripButtonAddFav_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            if (formChannelList.listViewChannels.SelectedItems.Count == 0) return;

            FormFavSetting formfv = new FormFavSetting();
            formfv.AddFavorite(formChannelList.listViewChannels.SelectedItems[0].SubItems[2].Text);
            if (formfv.ShowDialog() == DialogResult.OK)
            {
                ApplySetting();
            }
            formfv.Dispose();
        }

        private void menuItemTrayRef_Click(object sender, EventArgs e)
        {
            // this.toolStripButtonRefrsh.PerformClick();
            RefreshAllYp();
        }

        private void menuItemTrayYpSetting_Click(object sender, EventArgs e)
        {
            menuItemYPSetting.PerformClick();
        }

        private void menuItemTrayFavSetting_Click(object sender, EventArgs e)
        {
            menuItemFavSetting.PerformClick();
        }

        private void menuItemTrayPlayerSetting_Click(object sender, EventArgs e)
        {
            menuItemPlayerSetting.PerformClick();
        }

        private void menuItemTrayGeneralSetting_Click(object sender, EventArgs e)
        {
            menuItemGeneralSetting.PerformClick();
        }

        private void menuItemTrayExtTool_Click(object sender, EventArgs e)
        {
            menuItemExtToolSetting.PerformClick();
        }

        private void menuItemTrayRestoreWindow_Click(object sender, EventArgs e)
        {
            RestoreWindow();
        }

        private void menuItemTrayStartPeerCast_Click(object sender, EventArgs e)
        {
            PeerCast.StartPeerCast();
        }

        private void menuItemTrayClosePeerCast_Click(object sender, EventArgs e)
        {
            PeerCast.KillPeerCast(Settings.GeneralSetting.PeerCastPath);
        }

        private void menuItemTrayOpenInfo_Click(object sender, EventArgs e)
        {
            string url = string.Format("http://{0}/html/ja/index.html", Settings.GeneralSetting.NetworkSetting.HostAddr);
            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, url);
                return;
            }

            RestoreWindow();
            ShowBrowser(url);
            // formBrowser.menuItemOpenInfo.PerformClick();
        }

        private void menuItemTrayOpenRelays_Click(object sender, EventArgs e)
        {
            string url = string.Format("http://{0}/html/ja/relays.html", Settings.GeneralSetting.NetworkSetting.HostAddr);
            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, url);
                return;
            }

            RestoreWindow();
            ShowBrowser(url);
            // formChannelList.Pane.ActiveContent = formBrowser;
            // formBrowser.menuItemOpenRelay.PerformClick();
        }

        private void menuItemTrayOpenBroadcast_Click(object sender, EventArgs e)
        {
            string url = string.Format("http://{0}/html/ja/broadcast.html", Settings.GeneralSetting.NetworkSetting.HostAddr);
            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, url);
                return;
            }
            RestoreWindow();
            ShowBrowser(url);
            //formChannelList.Pane.ActiveContent = formBrowser;
            //formBrowser.menuItemOpenBroadcast.PerformClick();
        }

        private void menuItemTrayOpenConnections_Click(object sender, EventArgs e)
        {
            string url = string.Format("http://{0}/html/ja/connections.html", Settings.GeneralSetting.NetworkSetting.HostAddr);
            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, url);
                return;
            }
            RestoreWindow();
            ShowBrowser(url);
            //    formChannelList.Pane.ActiveContent = formBrowser;
            //    formBrowser.menuItemOpenConnection.PerformClick();
        }

        private void menuItemTrayOpenViewlog_Click(object sender, EventArgs e)
        {
            string url = string.Format("http://{0}/html/ja/viewlog.html", Settings.GeneralSetting.NetworkSetting.HostAddr);
            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, url);
                return;
            }
            RestoreWindow();
            ShowBrowser(url);
            //formChannelList.Pane.ActiveContent = formBrowser;
            //formBrowser.menuItemOpenLog.PerformClick();
        }

        private void menuItemTrayOpenSettings_Click(object sender, EventArgs e)
        {
            string url = string.Format("http://{0}/html/ja/settings.html", Settings.GeneralSetting.NetworkSetting.HostAddr);
            if (Settings.GeneralSetting.UseOtherBrowser)
            {
                Common.StartProcess(Settings.GeneralSetting.BrowserPath, url);
                return;
            }
            RestoreWindow();
            ShowBrowser(url);
            //formChannelList.Pane.ActiveContent = formBrowser;
            //formBrowser.menuItemOpenConfig.PerformClick();
        }

        private void menuItemTrayOpenPeerCastDir_Click(object sender, EventArgs e)
        {
            try
            {
                Process.Start(Path.GetDirectoryName(Settings.GeneralSetting.PeerCastPath));
            }
            catch { }
        }

        private void menuItemTrayExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void menuItemExtToolSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormToolSetting formt = new FormToolSetting();
            if (formt.ShowDialog() == DialogResult.OK)
                ApplySetting();
            formt.Dispose();
        }

        private void menuItemShowBrowser_Click(object sender, EventArgs e)
        {
            ShowBrowser();
        }

        private void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
        {
            //try
            //{
            //    sp.Stop();
            //}
            //catch { }

            if (notifyIcon1.Tag != null)
            {
                Channel item = notifyIcon1.Tag as Channel;
                if (item != null)
                    formChannelList.PlayChannel(item);
            }

            _balloonShowing = false;
        }

        private void notifyIcon1_BalloonTipClosed(object sender, EventArgs e)
        {
            _balloonShowing = false;
        }

        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && Settings.GeneralSetting.SingleClickToReturn)
            {
                menuItemTrayRestoreWindow.PerformClick();
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (!Settings.GeneralSetting.SingleClickToReturn)
                menuItemTrayRestoreWindow.PerformClick();
        }

        private void menuItemExtTool_DropDownOpening(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem item in menuItemExtTool.DropDownItems)
            {
                item.Enabled = !(formChannelList.listViewChannels.SelectedItems.Count == 0);
            }
        }

        private void menuItenNGSetting_Click(object sender, EventArgs e)
        {
            formChannelList.SaveColumnSetting();
            FormNGSetting formng = new FormNGSetting();
            if (formng.ShowDialog() == DialogResult.OK)
                ApplySetting();
            formng.Dispose();
        }

        private void toolStripSearchComboBox_KeyUp(object sender, KeyEventArgs e)
        {
            toolStripButtonSearch.Enabled = toolStripButtonSearch.Text.Length != 0;
            // Migemo無効
            // インクリメンタルサーチ
            formChannelList.ShowSearchChannels(new Regex(toolStripSearchComboBox.Text, RegexOptions.IgnoreCase));
        }


        void toolStripSearchComboBox_KeyUp_Migemo(object sender, KeyEventArgs e)
        {
            toolStripButtonSearch.Enabled = toolStripButtonSearch.Text.Length != 0;
            // Migemo有効
            // インクリメンタルサーチ
            formChannelList.ShowSearchChannels(migemo.GetRegex(toolStripSearchComboBox.Text));
        }

        private void toolStripButtonPlayChannel_Click(object sender, EventArgs e)
        {
            formChannelList.PlayChannel();
        }

        private void FormMain_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.F)
            {
                toolStripSearchComboBox.Focus();
            }
        }

        private void toolStripButtonClearSearch_Click(object sender, EventArgs e)
        {
            toolStripSearchComboBox.Text = string.Empty;
        }
    }
}