using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;

namespace Engineer.Controls
{
    public class WatermarklListView : ListView
    {

        public enum FixedItem
        {
            Top,
            Middle,
            Bottom,
            None
        }

        // Fields
        private int bottomItemIndex = -1;
        private object clientAreaMutex = new object();
        private bool doubleBuffering;
        private bool restoreGridLines;
        private int topItemIndex = -1;
        private int updateCount = -1;
        private Brush watermarkBrush;
        private string watermarkMessage;
        private bool watermarkVisible;
        private const int WatermarkY = 40;

        // Methods
        public void BeginUpdate()
        {
            this.BeginUpdate(FixedItem.None);
        }

        public void BeginUpdate(FixedItem position)
        {
            base.BeginUpdate();
            this.UpdateCount++;
            if ((this.UpdateCount == 0) && (position != FixedItem.None))
            {
                lock (this.clientAreaMutex)
                {
                    int num = -1;
                    int num2 = -1;
                    if (base.Items.Count > 0)
                    {
                        if ((position == FixedItem.Top) || (position == FixedItem.Middle))
                        {
                            num = 0;
                            while (num < (base.Items.Count - 1))
                            {
                                if (base.Items[num].Bounds.Y >= this.Font.Height)
                                {
                                    break;
                                }
                                num++;
                            }
                        }
                        if ((position == FixedItem.Bottom) || (position == FixedItem.Middle))
                        {
                            num2 = (position == FixedItem.Middle) ? num : 0;
                            while (num2 < (base.Items.Count - 1))
                            {
                                if ((base.Items[num2].Bounds.Y + base.Items[num2].Bounds.Height) >= base.Height)
                                {
                                    break;
                                }
                                num2++;
                            }
                        }
                    }
                    this.TopItemIndex = num;
                    this.BottomItemIndex = num2;
                }
            }
        }

        public void EndUpdate()
        {
            this.UpdateCount--;
            if (this.UpdateCount == -1)
            {
                lock (this.clientAreaMutex)
                {
                    int num3;
                    int topItemIndex = this.TopItemIndex;
                    int bottomItemIndex = this.BottomItemIndex;
                    if (base.Items.Count == 0)
                    {
                        topItemIndex = -1;
                        bottomItemIndex = -1;
                    }
                    if ((topItemIndex != -1) && (topItemIndex >= base.Items.Count))
                    {
                        topItemIndex = base.Items.Count - 1;
                    }
                    if ((bottomItemIndex != -1) && (bottomItemIndex >= base.Items.Count))
                    {
                        bottomItemIndex = base.Items.Count - 1;
                    }
                    if ((bottomItemIndex != -1) && (topItemIndex >= bottomItemIndex))
                    {
                        topItemIndex = bottomItemIndex;
                        bottomItemIndex = -1;
                    }
                    if ((topItemIndex != -1) && (bottomItemIndex != -1))
                    {
                        num3 = (base.Items[bottomItemIndex].Bounds.Y + base.Items[bottomItemIndex].Bounds.Height) - base.Items[topItemIndex].Bounds.Y;
                        if (base.Items[bottomItemIndex].Bounds.Y == base.Items[topItemIndex].Bounds.Y)
                        {
                            topItemIndex = -1;
                            bottomItemIndex = -1;
                        }
                        else
                        {
                            if (num3 >= base.Bounds.Height)
                            {
                                goto Label_0244;
                            }
                            while (num3 < base.Height)
                            {
                                topItemIndex--;
                                bottomItemIndex++;
                                if (topItemIndex < 0)
                                {
                                    topItemIndex = 0;
                                    bottomItemIndex = -1;
                                    break;
                                }
                                if (bottomItemIndex >= base.Items.Count)
                                {
                                    bottomItemIndex = base.Items.Count - 1;
                                    topItemIndex = -1;
                                    break;
                                }
                                num3 = (base.Items[bottomItemIndex].Bounds.Y + base.Items[bottomItemIndex].Bounds.Height) - base.Items[topItemIndex].Bounds.Y;
                            }
                        }
                    }
                    goto Label_024D;
                Label_01E1:
                    topItemIndex++;
                    bottomItemIndex--;
                    if (topItemIndex >= bottomItemIndex)
                    {
                        topItemIndex = bottomItemIndex;
                        bottomItemIndex = -1;
                        goto Label_024D;
                    }
                    num3 = (base.Items[bottomItemIndex].Bounds.Y + base.Items[bottomItemIndex].Bounds.Height) - base.Items[topItemIndex].Bounds.Y;
                Label_0244:
                    if (num3 > base.Height)
                    {
                        goto Label_01E1;
                    }
                Label_024D:
                    if ((topItemIndex != -1) && (bottomItemIndex == -1))
                    {
                        base.EnsureVisible(base.Items.Count - 1);
                        base.EnsureVisible(topItemIndex);
                    }
                    else if ((topItemIndex == -1) && (bottomItemIndex != -1))
                    {
                        base.EnsureVisible(0);
                        base.EnsureVisible(bottomItemIndex);
                    }
                    else if ((topItemIndex != -1) && (bottomItemIndex != -1))
                    {
                        base.EnsureVisible(bottomItemIndex);
                        base.EnsureVisible(topItemIndex);
                    }
                    this.TopItemIndex = -1;
                    this.BottomItemIndex = -1;
                }
            }
            base.EndUpdate();
        }

        [DllImport("user32")]
        public static extern int GetScrollPos(IntPtr handle, int scrollbar);
        [DllImport("user32")]
        private static extern IntPtr SendMessage(IntPtr handle, int type, IntPtr first, IntPtr second);
        [DllImport("user32", EntryPoint = "SendMessage")]
        private static extern IntPtr SendMessage2_ListViewHeader(IntPtr handle, int type, IntPtr first, ref ComCtlHDITEM second);
        public void SetColumnIcon(ColumnHeader column, SortOrder order)
        {
            try
            {
                IntPtr handle = SendMessage(base.Handle, 0x101f, IntPtr.Zero, IntPtr.Zero);
                ComCtlHDITEM second = new ComCtlHDITEM();
                second.mask = 4;
                second.fmt = 0x4000;
                if (this.RightToLeft == RightToLeft.Yes)
                {
                    second.fmt |= 4;
                }
                switch (column.TextAlign)
                {
                    case HorizontalAlignment.Left:
                        second.fmt = second.fmt;
                        second.fmt |= 0x1000;
                        break;

                    case HorizontalAlignment.Right:
                        second.fmt |= 0x4000;
                        break;

                    case HorizontalAlignment.Center:
                        second.fmt |= 2;
                        second.fmt |= 0x1000;
                        break;
                }
                switch (order)
                {
                    case SortOrder.Ascending:
                        second.fmt |= 0x400;
                        break;

                    case SortOrder.Descending:
                        second.fmt |= 0x200;
                        break;
                }
                SendMessage2_ListViewHeader(handle, 0x120c, new IntPtr(column.Index), ref second);
            }
            catch (Exception)
            {
            }
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            int msg = m.Msg;
            if (msg <= 0x114)
            {
                if (msg == 20)
                {
                    if (this.WatermarkVisible && (base.Items.Count > 0))
                    {
                        if (this.DoubleBuffering)
                        {
                            base.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
                        }
                        base.GridLines = this.RestoreGridLines;
                        base.Invalidate();
                        this.WatermarkVisible = false;
                        return;
                    }
                    if ((this.WatermarkMessage != null) && (base.Items.Count == 0))
                    {
                        if (!this.WatermarkVisible)
                        {
                            base.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
                            this.RestoreGridLines = base.GridLines;
                            base.GridLines = false;
                        }
                        Graphics graphics = base.CreateGraphics();
                        int num = 0;
                        num = base.Width - graphics.MeasureString(this.WatermarkMessage, this.Font).ToSize().Width;
                        num /= 2;
                        graphics.DrawString(this.WatermarkMessage, this.Font, this.WatermarkBrush, (float)num, 40f);
                        graphics.Dispose();
                        this.WatermarkVisible = true;
                    }
                    return;
                }
                if ((msg != 0x4e) && (msg != 0x114))
                {
                    return;
                }
            }
            else
            {
                switch (msg)
                {
                    case 0x20a:
                    case 0x1012:
                    case 0x101f:
                        goto Label_013E;

                    default:
                        return;
                }
            }
        Label_013E:
            if (this.WatermarkVisible)
            {
                base.Invalidate();
            }
        }

        // Properties
        protected int BottomItemIndex
        {
            get
            {
                return this.bottomItemIndex;
            }
            private set
            {
                this.bottomItemIndex = value;
            }
        }

        public bool DoubleBuffering
        {
            get
            {
                return this.doubleBuffering;
            }
            set
            {
                this.doubleBuffering = value;
            }
        }

        public bool GridLines
        {
            get
            {
                if (!this.WatermarkVisible)
                {
                    return base.GridLines;
                }
                return this.RestoreGridLines;
            }
            set
            {
                if (this.WatermarkVisible)
                {
                    this.RestoreGridLines = value;
                }
                else
                {
                    base.GridLines = value;
                }
            }
        }

        protected bool RestoreGridLines
        {
            get
            {
                return this.restoreGridLines;
            }
            private set
            {
                this.restoreGridLines = value;
            }
        }

        public bool ShowGroups
        {
            get
            {
                return base.ShowGroups;
            }
            set
            {
                if ((base.ShowGroups && !value) && (base.GridLines && (base.Items.Count > 0)))
                {
                    lock (this.clientAreaMutex)
                    {
                        base.EnsureVisible(base.Items.Count - 1);
                        base.EnsureVisible(0);
                    }
                }
                base.ShowGroups = value;
            }
        }

        protected int TopItemIndex
        {
            get
            {
                return this.topItemIndex;
            }
            private set
            {
                this.topItemIndex = value;
            }
        }

        protected int UpdateCount
        {
            get
            {
                return this.updateCount;
            }
            private set
            {
                this.updateCount = value;
            }
        }

        public Brush WatermarkBrush
        {
            get
            {
                if (this.watermarkBrush == null)
                {
                    return SystemBrushes.ControlText;
                }
                return this.watermarkBrush;
            }
            set
            {
                this.watermarkBrush = value;
            }
        }

        public string WatermarkMessage
        {
            get
            {
                return this.watermarkMessage;
            }
            set
            {
                this.watermarkMessage = value;
            }
        }

        public bool WatermarkVisible
        {
            get
            {
                return this.watermarkVisible;
            }
            set
            {
                this.watermarkVisible = value;
            }
        }

        // Nested Types
        [StructLayout(LayoutKind.Sequential)]
        private struct ComCtlHDITEM
        {
            public int mask;
            public int cxy;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string pszText;
            public IntPtr hbm;
            public int cchTextMax;
            public int fmt;
            public int lParam;
            public int iImage;
            public int iOrder;
        }

        [Flags]
        private enum ComCtlHeaderFormat
        {
            HDF_BITMAP = 0x2000,
            HDF_BITMAP_ON_RIGHT = 0x1000,
            HDF_CENTER = 2,
            HDF_IMAGE = 0x800,
            HDF_JUSTIFYMASK = 3,
            HDF_LEFT = 0,
            HDF_OWNERDRAW = 0x8000,
            HDF_RIGHT = 1,
            HDF_RTLREADING = 4,
            HDF_SORTDOWN = 0x200,
            HDF_SORTUP = 0x400,
            HDF_STRING = 0x4000
        }

        private enum ComCtlHeaderItem
        {
            HDI_BITMAP = 0x10,
            HDI_DI_SETITEM = 0x40,
            HDI_FILTER = 0x100,
            HDI_FORMAT = 4,
            HDI_HEIGHT = 1,
            HDI_IMAGE = 0x20,
            HDI_LPARAM = 8,
            HDI_ORDER = 0x80,
            HDI_TEXT = 2,
            HDI_WIDTH = 1
        }

        private enum ComCtlScrollbar
        {
            SB_HORZ,
            SB_VERT
        }

        private enum Win32Message
        {
            HDM_GETIMAGELIST = 0x1209,
            HDM_GETITEM = 0x120b,
            HDM_SETIMAGELIST = 0x1208,
            HDM_SETITEM = 0x120c,
            LVM_GETHEADER = 0x101f,
            LVM_SETSCROLL = 0x1014,
            WM_COLUMNADJ = 0x101f,
            WM_DRAGSCROLL = 0x4e,
            WM_ERASEBKGND = 20,
            WM_HSCROLL = 0x114,
            WM_MOUSEWHEEL = 0x20a,
            WM_NCPAINT = 0x85,
            WM_PAINT = 15,
            WM_THEMEPAINT = 0x1012
        }
    }

}