//ライセンス情報はAgeOnフォルダのLISENCEフォルダを参照してください
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using nispi.Menu;
using System.Threading;

namespace nispi.controlclass
{
    partial class ListViewParts : ControlBase
    {
        Thread t;

        void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            e.Item = this.items[e.ItemIndex].control;

            //if (this.allSelectFlag == true)
            //    e.Item.Selected = true;
        }

        void control_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            e.Graphics.FillRectangle(columnBackBrush, e.Bounds);
            e.Graphics.DrawString(e.Header.Text,
                control.Font,
                columnForeBrush, new PointF(e.Bounds.Left, e.Bounds.Top));
        }

        //通常のやり方
        void control_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            string text = GetMaxLengthTitleString(e.SubItem.Text, this.control.Columns[e.ColumnIndex].Width);


            //threadDataListのCountは生存スレの数のまま。過去ログを含む場合はextractionを利用するべきかも。
            //if (this.boardView.threadInfo == null) return;
            //if (this.boardView.threadInfo.threadDataList.Count <= e.ItemIndex) return;
            
            if (this.boardView.bvTimeExtraction.threadInfo != null)
                this.usingThreadData = this.boardView.bvTimeExtraction.threadInfo.threadDataList;
            else if (this.boardView.wordExtraction.threadInfo != null)
                this.usingThreadData = this.boardView.wordExtraction.threadInfo.threadDataList;
            else if (this.boardView.threadInfo != null)
                this.usingThreadData = this.boardView.threadInfo.threadDataList;

            if (this.usingThreadData.Count == 0)
                return;
            
            
            if (((e.ItemState & (ListViewItemStates.Selected)) == (ListViewItemStates.Selected)))
            {
                //ここでのマイナス２は微調整
                if ((Int32.Parse(this.usingThreadData[e.ItemIndex].readNum) != 0) &&
                (0 < ((Int32.Parse(this.usingThreadData[e.ItemIndex].resNum)) - Int32.Parse(this.usingThreadData[e.ItemIndex].readNum))))
                {
                    e.Graphics.DrawString(text, this.boldFont, lVSelectForeColorBrush, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Size.Width, e.Bounds.Size.Height - 2));
                }
                else
                {
                    e.Graphics.DrawString(text, control.Font, lVSelectForeColorBrush, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Size.Width, e.Bounds.Size.Height - 2));
                }
            }
            else
            {
                if ((Int32.Parse(this.usingThreadData[e.ItemIndex].readNum) != 0) &&
                (0 < ((Int32.Parse(this.usingThreadData[e.ItemIndex].resNum)) - Int32.Parse(this.usingThreadData[e.ItemIndex].readNum))))
                {
                    e.Graphics.DrawString(text, this.boldFont, lVForeColorBrush, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Size.Width, e.Bounds.Size.Height - 2));
                }
                else
                {
                    e.Graphics.DrawString(text, control.Font, lVForeColorBrush, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Size.Width, e.Bounds.Size.Height - 2));
                }
            }


            if (this.control.Focused == false)
            {
                if (oldItemNumList.Length > 0)
                {
                    if (oldItemNumList.Contains(e.ItemIndex) == true)
                    {
                        e.Graphics.FillRectangle(lVSelectBackColorBrush,
                            e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
                        if ((Int32.Parse(this.usingThreadData[e.ItemIndex].readNum) != 0) &&
                        (0 < ((Int32.Parse(this.usingThreadData[e.ItemIndex].resNum)) - Int32.Parse(this.usingThreadData[e.ItemIndex].readNum))))
                        {
                            e.Graphics.DrawString(text, this.boldFont, lVSelectForeColorBrush, e.Bounds);
                        }
                        else
                        {
                            e.Graphics.DrawString(text, control.Font, lVSelectForeColorBrush, e.Bounds);
                        }
                    }
                }
            }



            //新規スレッドを表示
            if (e.ColumnIndex == 0)
            {
                if (this.usingThreadData[e.ItemIndex].newThread == true)
                {
                    Rectangle rect = new Rectangle(new Point(e.Bounds.X, e.Bounds.Y), new Size(e.Bounds.Height, e.Bounds.Height));

                    e.Graphics.DrawImage(imageNew, rect);
                }
            }
            //ログを持っている場合に表示
            else if (e.ColumnIndex == 2)
            {
                if (e.Item.SubItems[2].Text.Equals(".") == true)
                {
                    Rectangle rect = new Rectangle(new Point(e.Bounds.X, e.Bounds.Y), new Size(e.Bounds.Height, e.Bounds.Height));
                    string url = this.usingThreadData[e.ItemIndex].datUrl;

                    string type = Util.BoardUrlToBoardTypeName(url);
                    int num = 0;
                    if (true == type.Equals("2chsc"))
                        num = 0;
                    else if (true == type.Equals("2ch"))
                        num = 1;
                    else if (true == type.Equals("favorite"))
                        num = 2;
                    else if (true == type.Equals("screening"))
                        num = 3;
                    else if (true == type.Equals("open2ch"))
                        num = 4;
                    else if (true == type.Equals("next2ch"))
                        num = 5;

                    else if (true == type.Equals("jikkyo"))
                        num = 6;
                    else if (true == type.Equals("blogban"))
                        num = 7;
                    else if (true == type.Equals("shizu"))
                        num = 8;

                    else if (true == type.Equals("vip2ch"))
                        num = 9;
                    else if (true == type.Equals("machibbs"))
                        num = 10;
                    else if (true == type.Equals("jbbs"))
                        num = 11;
                    else if (true == type.Equals("refind2ch"))
                        num = 12;

                    e.Graphics.DrawImage(Const.form.imageList.Images[num], rect);
                }
                else
                {
                    //string dir = Util.DatUrlToDatDirPath2(this.boardView.threadInfo.threadDataList[e.ItemIndex].datUrl);
                    //string datFileName = Util.DatUrlToDatFileName(this.boardView.threadInfo.threadDataList[e.ItemIndex].datUrl);
                    string dir = Util.DatUrlToDatDirPath2(this.usingThreadData[e.ItemIndex].datUrl);
                    string datFileName = Util.DatUrlToDatFileName(this.usingThreadData[e.ItemIndex].datUrl);
                    if (true == FileIO.CheckIsFile(dir + Path.DirectorySeparatorChar + datFileName))
                    {
                        Rectangle rect = new Rectangle(new Point(e.Bounds.X, e.Bounds.Y), new Size(e.Bounds.Height, e.Bounds.Height));

                        e.Graphics.DrawImage(imageLog, rect);
                    }
                }
            }
        }

        //工夫されたやり方
        /*void control_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            string text = GetMaxLengthTitleString(e.SubItem.Text);

            if (oldItemNumList.Contains(e.ItemIndex) == true)
            {
                e.Graphics.DrawString(text, control.Font, lVSelectForeColorBrush, e.Bounds);
            }
            else
            {
                e.Graphics.DrawString(text, control.Font, lVForeColorBrush, e.Bounds);
            }
        }*/

        void control_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            if (((e.State & (ListViewItemStates.Selected)) == (ListViewItemStates.Selected)))
            {
                e.Graphics.FillRectangle(lVSelectBackColorBrush,
                    e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
            }
            else
            {
                if ((e.ItemIndex % 2) == 0)
                    e.Graphics.FillRectangle(lVBackColorBrush,
                        e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
                else
                    e.Graphics.FillRectangle(lVBackColor2Brush,
                        e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);

                if (this.control.Focused == false)
                {
                    if (oldItemNumList.Length > 0)
                    {
                        if (oldItemNumList.Contains(e.ItemIndex) == true)
                            e.Graphics.FillRectangle(lVSelectBackColorBrush,
                                e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
                    }
                }
            }
        }

        //スレッド名を除いたカラムの幅の合計を得る
        //スレッド名以外カラムの幅も設定する
        private int GetListViewWidth()
        {
            //「ニュー」
            int newColumn = TextRenderer.MeasureText("ﾆｭｰ", control.Font).Width;//this.control.Items[0].Bounds.Height;
            int numColumn = TextRenderer.MeasureText("8888", control.Font).Width;
            int logColumn = TextRenderer.MeasureText("ﾛｸﾞ", control.Font).Width;//this.control.Items[0].Bounds.Height;
            //int threadNameColumn = columnThreadName.Width;
            int resColumn = TextRenderer.MeasureText("8888", control.Font).Width;
            int dayColumn = TextRenderer.MeasureText("00/00/00 00:000", control.Font).Width;
            int speedColumn = TextRenderer.MeasureText("speed0", control.Font).Width;
            int boardNameColumn = TextRenderer.MeasureText("最も長い板名は何", control.Font).Width;

            /*if(0 >= newColumn) newColumn = 10;
            if(0 >= numColumn) numColumn = 10;
            if (0 >= logColumn) logColumn = 10;
            if (0 >= resColumn) resColumn = 10;
            if (0 >= dayColumn) dayColumn = 10;
            if (0 >= speedColumn) speedColumn = 10;
            if (0 >= boardNameColumn) boardNameColumn = 10;*/

            control.Columns[0].Width = newColumn;
            control.Columns[1].Width = numColumn;
            control.Columns[2].Width = logColumn;
            control.Columns[4].Width = resColumn;
            control.Columns[5].Width = resColumn;
            control.Columns[6].Width = resColumn;
            control.Columns[7].Width = dayColumn;
            control.Columns[8].Width = speedColumn;
            control.Columns[9].Width = boardNameColumn;

            return newColumn + numColumn + logColumn + resColumn * 3 + dayColumn + speedColumn + boardNameColumn;
        }

        //カラムの幅での最大の文字数の文字列を得る
        private string GetMaxLengthTitleString(string text, int width)
        {
            Size size = TextRenderer.MeasureText(text, control.Font);
            int columnLength = width;

            int sa = columnLength - size.Width;

            if (sa > 0)
            {
                return text;
            }
            else
            {
                float wari = (((float)columnLength) / ((float)size.Width) * ((float)text.Length));
                int newTextWidth = (int)Math.Round(wari, MidpointRounding.AwayFromZero);
                string newText = Util.TruncatStr(text, newTextWidth - 4);

                for(int count = 0; TextRenderer.MeasureText(newText, control.Font).Width > (columnLength - 4); count+=1)
                {
                    newTextWidth -= 1;
                    newText = Util.TruncatStr(newText, newTextWidth - 4);
                    if (count > 10) break;
                }

                return newText;
            }
        }


        void listView_SizeChanged(object sender, EventArgs e)
        {
            int width = control.Size.Width - GetListViewWidth() - 25;
            if (width <= 0)
                width = 0;

            control.Columns[3].Width = width;
        }
        private void listView_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            string dat_url = "";
            try
            {
                dat_url = control.FocusedItem.Name;
                string thread_name = control.FocusedItem.SubItems[3].Text.ToString();
                boardView.ShowThread(dat_url, thread_name);
            }
            catch { ;}
        }


        //マウスが動いた時に、フォーカスが無いのならば与える（スクロールバークリック時に対応）
        public void listViewPart_MouseMove(object sender, EventArgs e)
        {
            ListViewEx listViewEx = (ListViewEx)sender;
            if (listViewEx.ContainsFocus == false)
            {
                //ポップアップウィンドウがある場合は無条件で消す
                if (MainFormConst.htmlPopUpWindowWidget.popUpList.Count > 0)
                {
                    //System.Diagnostics.Debug.WriteLine("focusp");
                    MainFormConst.htmlPopUpWindowWidget.RemoveAllPopUp();
                    listViewEx.Focus();
                }
                listViewEx.Refresh();
                GetFocus(listViewEx);
            }
        }

        public void listViewPart_SelectedIndexChanged(object sender, EventArgs e)
        {
            oldItemNumList = null;
            oldItemNumList = new int[control.SelectedIndices.Count];
            control.SelectedIndices.CopyTo(oldItemNumList, 0);


            //this.control.Refresh();
            //this.control.Invalidate();
            //this.control.Update(); 

            if (control.SelectedIndices.Count == 0)
                return;

            /*try
            {
                if ((this.oldItemNumList != null) && (this.oldItemNumList.Length != 0))
                {
                    foreach (int num in this.oldItemNumList)
                    {
                        this.items[num].ForeColor = SystemColors.MenuText;

                        if ((num % 2) == 0)
                            this.items[num].BackColor = System.Drawing.Color.AliceBlue;
                        else
                            this.items[num].BackColor = System.Drawing.Color.White;
                    }
                }
                //int[] newItemNumList = new int[control.SelectedIndices.Count];
                oldItemNumList = new int[control.SelectedIndices.Count];
                control.SelectedIndices.CopyTo(oldItemNumList, 0);
                //control.SelectedIndices.CopyTo(newItemNumList, 0);

                if ((oldItemNumList != null) && (oldItemNumList.Length != 0))
                {
                    foreach (int num in oldItemNumList)
                    {
                        this.items[num].BackColor = SystemColors.MenuHighlight;
                        this.items[num].ForeColor = System.Drawing.Color.White;
                    }
                }
            }
            catch
            {
            }
            return;*/
        }

        private void ListView_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Modifiers & Keys.Shift) == Keys.Shift)
            {
                ShiftFlag = true;
            }
        }
        private void ListView_KeyUp(object sender, KeyEventArgs e)
        {
            ShiftFlag = false;
        }

        private void listView_MouseUp(Object sender, MouseEventArgs e)
        {
            try
            {
                //マウスのあるNodeを取得する
                ListViewEx tv = (ListViewEx)sender;
                ListViewItem target = tv.GetItemAt(e.X, e.Y);
                //マウス下のNodeがドロップ先として適切か調べる
                if (target != null)
                {
                    //Nodeを選択する
                    //if (target.Selected == false)
                    //{
                    //tv.Items[target.Index].Selected = true;
                    //tv.Items[target.Index].Focused = true;
                    if (ShiftFlag == true)
                    {
                        //foreach(int num3 in oldItemNumList)
                        ///   this.ite
                        int begin = 0;
                        int end = 0;

                        if (target.Index > ShiftFlagBeginNum)
                        {
                            begin = ShiftFlagBeginNum;
                            end = target.Index;
                        }
                        else
                        {
                            begin = target.Index;
                            end = ShiftFlagBeginNum;
                        }

                        oldItemNumList = null;
                        oldItemNumList = new int[end - begin + 1];

                        for (int num2 = 0; begin <= end; begin += 1, num2 += 1)
                        {
                            oldItemNumList[num2] = begin;
                        }

                        ShiftFlagBeginNum = target.Index;

                        this.control.Refresh();
                        //this.control.Invalidate();
                        //this.control.Update();

                        return;
                    }
                }
                else
                    return;

                ShiftFlagBeginNum = target.Index;
                //右クリック時はリストの選択だけをする
                if (e.Button == MouseButtons.Right)
                {
                    ContextMenuControls.listViewMenu.listViewPartMenuEvent.Show(e.Location);
                }
                else if (e.Button == MouseButtons.Left)
                {
                    //マウスがコントロール上に入ったのちにマウス押下するという順番でないと開かないように
                    if (mouseDownNum == mouseEnterNum)
                    {
                        int num = control.FocusedItem.Index;
                        string dat_url = control.FocusedItem.Name;
                        string thread_name = control.FocusedItem.SubItems[3].Text.ToString();
                        Const.form.mainForm.BeginInvoke((Action)(() => boardView.ShowThreadInBeginInvoke(dat_url, thread_name)));

                        ListViewPartMethodUtil.ChangeReadNum(this.boardView, this.boardView.boardListControls.listViewParts, "read");
                        //this.boardView.boardListControls.listViewParts.Refresh();
                    }
                }
                else if (e.Button == MouseButtons.Middle)
                {
                    MouseGesture.mutex.WaitOne();
                    if (MouseGesture.ON_OFF.Equals("OFF") == true)
                    {
                        MouseGesture.mutex.ReleaseMutex();

                        Thread.Sleep(100);
                        MouseGesture mouseGesture = new MouseGesture();
                        t = new Thread(new ThreadStart(mouseGesture.SetUpTwo));
                        //t.IsBackground = true;
                        t.Start();
                    }
                    else
                        MouseGesture.mutex.ReleaseMutex();

                }
            }
            catch { ;}
        }
        //マウスが外に出た場合の対応
        private void listView_MouseDown(Object sender, MouseEventArgs e)
        {
            //マウス押下するたびに代入する。
            mouseDownNum = mouseEnterNum;
        }
        private void listView_Enter(Object sender, EventArgs e)
        {
            //マウスがコントロール上に入るたびに数を更新する
            mouseEnterNum += 1;
        }
        private void control_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
        {
            //toolTipParts.Text = e.Item.SubItems[3].Text.ToString();
            toolTipParts.HideToolTip();
            toolTipParts.ShowToolTip2(e.Item.SubItems[3].Text.ToString(), this);
        }
        private void control_MouseLeave(object sender, EventArgs e)
        {
            toolTipParts.HideToolTip();
        }
        //ソート関連
        public void listView_ColumnClick(object sender, ColumnClickEventArgs e)
        {

            try
            {
                List<ThreadData> threadList;
                threadList = boardView.threadInfo.threadDataList;

                if (boardView.bvTimeExtraction.threadInfo != null)
                    threadList = boardView.bvTimeExtraction.threadInfo.threadDataList;


                //２ｃｈでのレスの順番
                if (e.Column == 1)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareOrderNumRev);
                    else
                        threadList.Sort(BoadListSort.CompareOrderNum);
                }

                //タイトル
                else if (e.Column == 3)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareTitleRev);
                    else
                        threadList.Sort(BoadListSort.CompareTitle);
                }
                //レスの数
                else if (e.Column == 4)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareResNumRev);
                    else
                        threadList.Sort(BoadListSort.CompareResNum);
                }
                //読んだレスの数
                else if (e.Column == 5)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareReadNumRev);
                    else
                        threadList.Sort(BoadListSort.CompareReadNum);
                }
                //未読のレスの数
                else if (e.Column == 6)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareNoReadNumRev);
                    else
                        threadList.Sort(BoadListSort.CompareNoReadNum);
                }
                //開いた時間
                else if (e.Column == 7)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareOpenTimeRev);
                    else
                        threadList.Sort(BoadListSort.CompareOpenTime);
                }
                //レスの更新速度
                else if (e.Column == 8)
                {
                    if (boardView.beforeNum == e.Column)
                        threadList.Sort(BoadListSort.CompareSpeedRev);
                    else
                        threadList.Sort(BoadListSort.CompareSpeed);
                }
                //コントロールの更新
                boardView.WriteList();

                //前の数と同じなら初期化
                if (boardView.beforeNum == e.Column)
                    boardView.beforeNum = -1;
                else
                    boardView.beforeNum = e.Column;
            }
            catch { ;}
        }
    }
}
