/* Copyright (c) Citrix Systems, Inc. 
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met: 
 * 
 * *   Redistributions of source code must retain the above 
 *     copyright notice, this list of conditions and the 
 *     following disclaimer. 
 * *   Redistributions in binary form must reproduce the above 
 *     copyright notice, this list of conditions and the 
 *     following disclaimer in the documentation and/or other 
 *     materials provided with the distribution. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;

using XenAdmin.Core;
using XenAdmin.Dialogs;
using XenAdmin.Dialogs.Wlb;
using XenAdmin.Wlb;
using XenAPI;


namespace XenAdmin.Controls.Wlb
{
    public partial class WlbOptModeScheduler : UserControl
    {
        #region Color Constants

        private Color COLOR_MAX_PERFORMANCE = Color.White; // Color.FromArgb(30, 49, 191);
        private Color COLOR_MAX_DENSITY = Color.White; // Color.FromArgb(30, 191, 30);
        private Color COLOR_MAX_PERFORMANCE_SUBITEM_TEXT = Color.Black; //Color.White;
        private Color COLOR_MAX_DENSITY_SUBITEM_TEXT = Color.DarkGreen; //Color.White;
        private Color COLOR_HIGHLIGHTED_MAX_PERFORMANCE_SUBITEM_TEXT = Color.White; //Color.White;
        private Color COLOR_HIGHLIGHTED_MAX_DENSITY_SUBITEM_TEXT = Color.LightGreen; //Color.White;
        private Color COLOR_NEW_DAY = Color.LightBlue; // Color.Yellow;
        private Color COLOR_DISABLED_TASK = Color.Gray;
        private Color COLOR_DUPLICATE_TASK = Color.Red;

        #endregion
        
        #region Private Fields

        private WlbScheduledTasks _scheduledTasks;
        private int _newTaskId = 0;
        private WlbPoolPerformanceMode _baseMode = WlbPoolPerformanceMode.MaximizePerformance;
        private Pool _pool = null;
        private bool _hasChanged = false;

        private bool _initializing = false;

        // Listview minimum column widths
        private int[] minimumColumnWidths = { 0, 60, 60, 60, 60 };


        #endregion Private Fields

        #region Public CTor
        public WlbOptModeScheduler()
        {
            InitializeComponent();
        }
        #endregion Public CTor

        #region Public Properties
        public Pool Pool
        {
            set
            {
                _pool = value;
                InitializeControls();
            }
        }

        public WlbPoolPerformanceMode BaseMode
        {
            set
            {
                _baseMode = value;
                InitializeControls();
            }
        }

        public WlbScheduledTasks ScheduledTasks
        {
            get { return _scheduledTasks; }
            set
            {
                if (null != value)
                {
                    _scheduledTasks = new WlbScheduledTasks();
                    //Clone the tasks so local edits don't affect the base collection
                    foreach (string key in value.TaskList.Keys)
                    {
                        _scheduledTasks.TaskList.Add(key, value.TaskList[key]);
                    }
                    InitializeControls();
                }
            }
        }

        public bool HasChanged
        {
            get { return _hasChanged; }
        }

        #endregion Public Properties

        #region Public Methods

        public void RefreshScheduleList()
        {
            PopulateListView();
        }

        #endregion
        
        #region Private Methods
        private void SetUpListView()
        {
            lvTaskList.Columns[0].Width = 0;  // sorting column
            if (lvTaskList.Columns.Count > 1)
            {
                for (int iCol = 1; iCol < lvTaskList.Columns.Count; iCol++)
                {
                    lvTaskList.Columns[iCol].Width = lvTaskList.Width / (lvTaskList.Columns.Count - 1);
                }
            } 
            lvTaskList.ListViewItemSorter = new ListViewItemComparer(0);
        }

        private void InitializeControls()
        {
            typeof(WeekView).InvokeMember("DoubleBuffered", System.Reflection.BindingFlags.SetProperty | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, weekView1, new object[] { true });

            if (null != _pool && null != _scheduledTasks)
            {
                _initializing = true;
                buttonEdit.Enabled = false;
                buttonDelete.Enabled = false;

                SetUpListView();
                PopulateListView();
                //PopulateWeekView();
                _initializing = false;
            }
        }

        private void PopulateListView()
        {
            weekView1.ClearTriggerPoints();
            lvTaskList.Items.Clear();

            //foreach (int key in _scheduledTasks.SortedTaskList.Keys)
            foreach (int key in _scheduledTasks.VirtualTaskList.Keys)
            {
                //WlbScheduledTask task = _scheduledTasks.SortedTaskList[key];
                WlbScheduledTask task = _scheduledTasks.VirtualTaskList[key];
                WlbScheduledTask parentTask = _scheduledTasks.TaskList[_scheduledTasks.VirtualTaskList[key].TaskId.ToString()];

                DateTime localExecuteTime;
                WlbScheduledTask.WlbTaskDaysOfWeek localDaysOfWeek;
                WlbScheduledTask.GetLocalTaskTimes((task.DaysOfWeek), task.ExecuteTime, out localDaysOfWeek, out localExecuteTime);

                ListViewItem item = new ListViewItem();
                item.Text = key.ToString();
                item.SubItems.Add(GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizeDensity ? Messages.WLB_OPT_MODE_MAXIMIZEDENSITY : Messages.WLB_OPT_MODE_MAXIMIZEPERFORMANCE);
                item.SubItems.Add(GetTaskDayOfWeek(localDaysOfWeek, parentTask.DaysOfWeek));
                item.SubItems.Add(GetTaskExecuteTime(localExecuteTime));
                item.SubItems.Add(task.Enabled ? Messages.YES : Messages.NO);
                item.Tag = task;
                lvTaskList.Items.Add(item);
            //}

            //foreach (WlbScheduledTask task in _scheduledTasks.VirtualTaskList.Values)
            //{
                if (task.Enabled)
                {
                    //DateTime localExecuteTime;
                    //WlbScheduledTask.WlbTaskDaysOfWeek localDaysOfWeek;
                    WlbScheduledTask.GetLocalTaskTimes((task.DaysOfWeek), task.ExecuteTime, out localDaysOfWeek, out localExecuteTime);
                    string toolTipText = string.Format("Change to {0} mode at {1} on {2}", WlbScheduledTask.GetTaskOptMode(task), WlbScheduledTask.GetTaskExecuteTime(localExecuteTime), WlbScheduledTask.DaysOfWeekL10N(localDaysOfWeek));
                    
                    TriggerPoint triggerPoint = new TriggerPoint();
                    triggerPoint.Day = WlbScheduledTask.ConvertFromWlbTaskDayOfWeek(localDaysOfWeek);
                    triggerPoint.Hour = localExecuteTime.Hour;
                    triggerPoint.Color = GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizePerformance ? Color.Blue : Color.Green;
                    triggerPoint.ToolTip = toolTipText;
                    triggerPoint.Tag = task.TaskId;
                    weekView1.AddTriggerPoint(triggerPoint);
                }

            }

            lvTaskList.Sort();
            EnableButtons();
       }

        //private void AddTaskToList(WlbScheduledTask task)
        //{
        //    foreach (WlbScheduledTask.WlbTaskDaysOfWeek dayValue in Enum.GetValues(typeof(WlbScheduledTask.WlbTaskDaysOfWeek)))
        //    {
        //        if (dayValue != WlbScheduledTask.WlbTaskDaysOfWeek.None && 
        //            dayValue != WlbScheduledTask.WlbTaskDaysOfWeek.All &&
        //            dayValue != WlbScheduledTask.WlbTaskDaysOfWeek.Weekdays &&
        //            dayValue != WlbScheduledTask.WlbTaskDaysOfWeek.Weekends &&
        //            ((task.DaysOfWeek & dayValue) == dayValue))
        //        {
        //            DateTime localExecuteTime;
        //            WlbScheduledTask.WlbTaskDaysOfWeek localDaysOfWeek;
        //            WlbScheduledTask.GetLocalTaskTimes((task.DaysOfWeek & dayValue), task.ExecuteTime, out localDaysOfWeek, out localExecuteTime);

        //            int sortValue = (int)localDaysOfWeek * 10000 + (int)localExecuteTime.TimeOfDay.TotalMinutes;

        //            ListViewItem item = new ListViewItem();
        //            item.Text = sortValue.ToString();
        //            item.SubItems.Add(GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizeDensity ? Messages.WLB_OPT_MODE_MAXIMIZEDENSITY : Messages.WLB_OPT_MODE_MAXIMIZEPERFORMANCE);
        //            item.SubItems.Add(GetTaskDayOfWeek(localDaysOfWeek));
        //            item.SubItems.Add(GetTaskExecuteTime(localExecuteTime));
        //            item.SubItems.Add(task.Enabled ? Messages.YES : Messages.NO);
        //            item.Tag = task;
        //            lvTaskList.Items.Add(item);
        //        }
        //    }
        //}

        private void FixColumnWidths()
        {
            //Make sure the last column always spans the width of the control
            int otherColumnWidths = 0;
            if (lvTaskList.Columns.Count > 0)
            {
                // skip sorting column (index 0)
                for (int i = 1; i < (lvTaskList.Columns.Count - 1); i++)
                {
                    otherColumnWidths += lvTaskList.Columns[i].Width;
                }
                if (otherColumnWidths < lvTaskList.Width)
                {
                    lvTaskList.ColumnWidthChanged -= new System.Windows.Forms.ColumnWidthChangedEventHandler(lvTaskList_ColumnWidthChanged);
                    lvTaskList.Columns[lvTaskList.Columns.Count - 1].Width = lvTaskList.Width - otherColumnWidths;
                    lvTaskList.ColumnWidthChanged += new System.Windows.Forms.ColumnWidthChangedEventHandler(lvTaskList_ColumnWidthChanged);
                }
            }
        }

        private void AddTask()
        {
            WlbEditScheduledTask addTask = new WlbEditScheduledTask(_newTaskId--, WlbScheduledTask.WlbTaskActionType.SetOptimizationMode);
            DialogResult dr = addTask.ShowDialog();
            if (DialogResult.OK == dr)
            {
                WlbScheduledTask newTask = addTask.Task;
                newTask.Owner = _pool.Connection.Username;
                newTask.LastTouchedBy = _pool.Connection.Username;
                newTask.AddTaskParameter("PoolUUID", _pool.uuid);

                WlbScheduledTask checkTask = CheckForDuplicateTask(newTask);
                if (null != checkTask)
                {
                    using (var dlg = new ThreeButtonDialog(
                       new ThreeButtonDialog.Details(
                           SystemIcons.Warning,
                           Messages.WLB_TASK_SCHEDULE_CONFLICT_BLURB,
                           Messages.WLB_TASK_SCHEDULE_CONFLICT_TITLE)))
                    {
                        dlg.ShowDialog(this);
                    }
                    SelectTask(checkTask.TaskId);
                }
                else
                {
                    _scheduledTasks.TaskList.Add(newTask.TaskId.ToString(), newTask);
                    PopulateListView();
                    _hasChanged = true;
                }
            }
        }

        private void EditTask(WlbScheduledTask task)
        {
            WlbScheduledTask editTask = task.Clone();
            WlbEditScheduledTask taskEditor = new WlbEditScheduledTask(editTask);
            DialogResult dr = taskEditor.ShowDialog();
            if (DialogResult.OK == dr)
            {
                WlbScheduledTask checkTask = CheckForDuplicateTask(editTask);
                if (null != checkTask)
                {
                    using (var dlg = new ThreeButtonDialog(
                       new ThreeButtonDialog.Details(
                           SystemIcons.Warning,
                           Messages.WLB_TASK_SCHEDULE_CONFLICT_BLURB,
                           Messages.WLB_TASK_SCHEDULE_CONFLICT_TITLE)))
                    {
                        dlg.ShowDialog(this);
                    }
                    SelectTask(checkTask.TaskId);
                }
                else
                {
                    editTask.LastTouchedBy = _pool.Connection.Username;
                    editTask.LastTouched = DateTime.UtcNow;
                    _scheduledTasks.TaskList[editTask.TaskId.ToString()] = editTask;
                    PopulateListView();
                    _hasChanged = true;
                }
            }
        }

        private WlbScheduledTask CheckForDuplicateTask(WlbScheduledTask newTask)
        {
            WlbScheduledTask checkTask;
            foreach (string key in _scheduledTasks.TaskList.Keys)
            {
                checkTask = _scheduledTasks.TaskList[key];
                if (checkTask.Enabled && !checkTask.DeleteTask)
                {
                    if ((checkTask.ActionType == newTask.ActionType) &&
                        ((checkTask.DaysOfWeek & newTask.DaysOfWeek) == checkTask.DaysOfWeek ||
                        (checkTask.DaysOfWeek & newTask.DaysOfWeek) == newTask.DaysOfWeek) &&
                        (string.Compare(HelpersGUI.DateTimeToString(checkTask.ExecuteTime, "t", false), HelpersGUI.DateTimeToString(newTask.ExecuteTime, "t", false)) == 0) &&
                        (checkTask.TaskId != newTask.TaskId))
                    {
                        return checkTask; // taskExists = true;
                    }
                }
            }
            return null;
        }

       private void DeleteTask(WlbScheduledTask task)
        {
            // if this is a new, unsaved task, simply delete it from the collection
            if (task.TaskId <= 0)
            {
                _scheduledTasks.TaskList.Remove(task.TaskId.ToString());
            }
            // otherwise, leave it in the collection but mark it for deletion
            else
            {
                task.DeleteTask = true;
            }
            PopulateListView();
            _hasChanged = true;
        }

       private void EnableTask(WlbScheduledTask task)
       {
           //If we are trying to enable the task, check to see if it is a duplicate before allowing it
           if (!task.Enabled)
           {
               //We need to pretend the task is enabled to check for duplicates
               WlbScheduledTask enabledTask = task.Clone();
               enabledTask.Enabled = true;
               WlbScheduledTask checkTask = CheckForDuplicateTask(enabledTask);
               //if it's a duplicate task, display warning and return
               if (null != checkTask)
               {
                   using (var dlg = new ThreeButtonDialog(
                       new ThreeButtonDialog.Details(
                           SystemIcons.Warning,
                           Messages.WLB_TASK_SCHEDULE_CONFLICT_BLURB,
                           Messages.WLB_TASK_SCHEDULE_CONFLICT_TITLE)))
                   {
                       dlg.ShowDialog(this);
                   }
                   SelectTask(checkTask.TaskId);
                   return;
               }
           }           
           task.Enabled = !task.Enabled;
           PopulateListView();
           _hasChanged = true;         

       }

        private void EnableButtons()
        {
            // If an item is selected, enable the edit and delete buttons
            buttonEdit.Enabled = (lvTaskList.SelectedItems != null && lvTaskList.SelectedItems.Count > 0);
            buttonDelete.Enabled = (lvTaskList.SelectedItems != null && lvTaskList.SelectedItems.Count > 0);
        }

        private void HighlightTrigger()
        {
            weekView1.TriggerPoints.ClearSelected();

            if (lvTaskList.SelectedItems.Count > 0)
            {
                int selectedTaskId = ((WlbScheduledTask)lvTaskList.SelectedItems[0].Tag).TaskId;
                TriggerPoints triggerPoints =  weekView1.TriggerPoints.FindByTag(selectedTaskId);
                if (null != triggerPoints)
                {
                    foreach (TriggerPoint triggerPoint in triggerPoints.List.Values)
                    {
                        triggerPoint.IsSelected = true;
                    }
                }
                weekView1.Refresh();
            }
        }

        private void SelectTask(int taskId)
        {
            foreach (ListViewItem listViewItem in lvTaskList.Items)
            {
                if (((WlbScheduledTask)listViewItem.Tag).TaskId == taskId)
                {
                    listViewItem.Selected = true;
                }
                else
                {
                    listViewItem.Selected = false;
                }
            }
        }

        private void EnableTask_Click(object sender, EventArgs e)
        {
            EnableTask(TaskFromItem(lvTaskList.SelectedItems[0]));
        }

        #endregion Private Methods

        #region Private Static Methods
        private static WlbPoolPerformanceMode GetTaskOptMode(WlbScheduledTask task)
        {
            WlbPoolPerformanceMode mode = WlbPoolPerformanceMode.MaximizePerformance;

            if (task.TaskParameters["OptMode"] == "0")
            {
                mode = WlbPoolPerformanceMode.MaximizePerformance;
            }
            else
            {
                mode = WlbPoolPerformanceMode.MaximizeDensity;
            }
            return mode;
        }

        /// <summary>
        /// Returns the number of bit set in an integer
        /// </summary>
        public static uint Bitcount(int n)
        {
            uint count = 0;
            while (n != 0)
            {
                count++;
                n &= (n - 1);
            }
            return count;
        }


        private static string GetTaskDayOfWeek(WlbScheduledTask.WlbTaskDaysOfWeek taskDaysOfWeek)
        {
            return WlbScheduledTask.DaysOfWeekL10N(taskDaysOfWeek);
        }

        private static string GetTaskDayOfWeek(WlbScheduledTask.WlbTaskDaysOfWeek taskDaysOfWeek,
            WlbScheduledTask.WlbTaskDaysOfWeek taskDaysofWeekSortedList)
        {
            string returnStr = "";
            returnStr += WlbScheduledTask.DaysOfWeekL10N(taskDaysOfWeek);

            //count the bits set in days of week.
            //this workaround had to be made to determine whether the original task was set for
            //weekends/weekdays/alldays
            uint bitCount = Bitcount((int)taskDaysofWeekSortedList);
            if (bitCount == 2)
            {
                returnStr += " (" + Messages.ResourceManager.GetString("WLB_DAY_WEEKENDS") + ")";
            }
            else if (bitCount == 5)
            {
                returnStr += " (" + Messages.ResourceManager.GetString("WLB_DAY_WEEKDAYS") + ")";
            }
            else if (bitCount == 7)
            {
                returnStr += " (" + Messages.ResourceManager.GetString("WLB_DAY_ALL") + ")";
            }
            
            return returnStr;
        }

        private static string GetTaskExecuteTime(DateTime TaskExecuteTime)
        {
            return HelpersGUI.DateTimeToString(TaskExecuteTime, Messages.DATEFORMAT_HM, true);
        }


        #endregion Private Static Methods

        #region ListView Custom Rendering Event Handlers
 
        private void lvTaskList_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            // Draw default column header
            e.DrawDefault = true;
        }

        private WlbScheduledTask TaskFromItem(ListViewItem item)
        {
            return _scheduledTasks.TaskList[((WlbScheduledTask)item.Tag).TaskId.ToString()];
        }

        private void lvTaskList_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            //Get the task associated with the list view item
            WlbScheduledTask task = TaskFromItem(e.Item);

            //Set the row color based on the Opt Mode
            Color color = GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizePerformance ? COLOR_MAX_PERFORMANCE : COLOR_MAX_DENSITY;

            if (!task.Enabled)
            {
                color = COLOR_DISABLED_TASK;
            }

            // Fill the full width of the control, not just to the end of the column headers.
            Rectangle rect = e.Bounds;
            int i = 0;
            foreach (ColumnHeader col in lvTaskList.Columns)
            {
                i += col.Width;
            }
            // Fill from the right of the rightmost item to the end of the control
            rect.Width = Math.Max(i, lvTaskList.ClientSize.Width);
            rect.X = i;

            if (e.Item.Selected)
            {
                using (SolidBrush brush = new SolidBrush(SystemColors.Highlight))
                    e.Graphics.FillRectangle(brush, rect);
            }
            else
            {
                Rectangle topRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height / 2);
                Rectangle botRect = new Rectangle(rect.X, rect.Y + topRect.Height, rect.Width, rect.Height / 2);
                if (e.ItemIndex == 0 || (e.ItemIndex > 0 && lvTaskList.Items[e.ItemIndex - 1].SubItems[2].Text != e.Item.SubItems[2].Text))
                {
                    using (LinearGradientBrush brush = new LinearGradientBrush(topRect, COLOR_NEW_DAY, ControlPaint.LightLight(color), 90f)) // SystemBrushes.Highlight;
                    {
                        e.Graphics.FillRectangle(brush, topRect);
                    }
                }
                else
                {
                    using (LinearGradientBrush brush = new LinearGradientBrush(topRect, color, ControlPaint.LightLight(color), 90f)) // SystemBrushes.Highlight;
                    {
                        e.Graphics.FillRectangle(brush, topRect);
                    }
                }
                using (LinearGradientBrush brush = new LinearGradientBrush(botRect, ControlPaint.LightLight(color), color, 90f)) // SystemBrushes.Highlight;
                {
                    e.Graphics.FillRectangle(brush, botRect);
                }
            }
        }

        private void lvTaskList_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            //Get the task associated with the list view item
            WlbScheduledTask task = TaskFromItem(e.Item);

            //Set the row color based on the Opt Mode
            Color color = GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizePerformance ? COLOR_MAX_PERFORMANCE : COLOR_MAX_DENSITY;
            Color subItemTextColor = GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizePerformance ? COLOR_MAX_PERFORMANCE_SUBITEM_TEXT : COLOR_MAX_DENSITY_SUBITEM_TEXT;

            if (!task.Enabled)
            {
                subItemTextColor = COLOR_DISABLED_TASK;
            }
            
            //Get the base rectangle
            Rectangle rect = e.Bounds;

            if (e.Item.Selected)
            {
                using (SolidBrush brush = new SolidBrush(SystemColors.Highlight))
                    e.Graphics.FillRectangle(brush, rect);
                subItemTextColor = GetTaskOptMode(task) == WlbPoolPerformanceMode.MaximizePerformance ? COLOR_HIGHLIGHTED_MAX_PERFORMANCE_SUBITEM_TEXT : COLOR_HIGHLIGHTED_MAX_DENSITY_SUBITEM_TEXT;
            }
            else
            {
                Rectangle topRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height / 2);
                Rectangle botRect = new Rectangle(rect.X, rect.Y + topRect.Height, rect.Width, rect.Height / 2);
                if (e.ItemIndex ==0 || (e.ItemIndex> 0 && lvTaskList.Items[e.ItemIndex - 1].SubItems[2].Text != e.Item.SubItems[2].Text))
                {
                    using (LinearGradientBrush brush = new LinearGradientBrush(topRect, COLOR_NEW_DAY, ControlPaint.LightLight(color), 90f)) // SystemBrushes.Highlight;
                    {
                        e.Graphics.FillRectangle(brush, topRect);
                    }
                }
                else
                {
                    using (LinearGradientBrush brush = new LinearGradientBrush(topRect, color, ControlPaint.LightLight(color), 90f)) // SystemBrushes.Highlight;
                    {
                        e.Graphics.FillRectangle(brush, topRect);
                    }
                }
                using (LinearGradientBrush brush = new LinearGradientBrush(botRect, ControlPaint.LightLight(color), color, 90f)) // SystemBrushes.Highlight;
                {
                    e.Graphics.FillRectangle(brush, botRect);
                }
            }

            // Draw subitem text
            Font font = new Font(this.Font, FontStyle.Regular); // FontStyle.Bold);
            TextRenderer.DrawText(e.Graphics, e.Item.SubItems[e.ColumnIndex].Text, font, e.Bounds, subItemTextColor, TextFormatFlags.EndEllipsis);
        }

        #endregion 

        #region Control Event Handlers

        private void buttonAddNew_Click(object sender, EventArgs e)
        {
            AddTask();
        }

        private void buttonEdit_Click(object sender, EventArgs e)
        {
            WlbScheduledTask task = TaskFromItem(lvTaskList.SelectedItems[0]);
            EditTask(task);
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            if (lvTaskList.SelectedItems.Count > 0)
            {
                DialogResult confirmResult;
                using (var dlg = new ThreeButtonDialog(
                                                new ThreeButtonDialog.Details(SystemIcons.Warning,
                                                                                Messages.DELETE_WLB_OPTIMIZATION_SCHEDULE_WARNING,
                                                                                Messages.DELETE_WLB_OPTIMIZATION_SCHEDULE_CAPTION),
                                                ThreeButtonDialog.ButtonYes,
                                                ThreeButtonDialog.ButtonNo))
                {
                    confirmResult = dlg.ShowDialog(this);
                }

                if (confirmResult == DialogResult.Yes)
                {
                    WlbScheduledTask task = TaskFromItem(lvTaskList.SelectedItems[0]);
                    DeleteTask(task);
                    weekView1.Refresh();
                }
            }
        }

        private void lvTaskList_SelectedIndexChanged(object sender, EventArgs e)
        {            
            EnableButtons();
            HighlightTrigger();            
        }

        private void lvTaskList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //Edit task on double-click
            ListViewHitTestInfo htInfo = lvTaskList.HitTest(e.Location);
            if (null != htInfo.Item)
            {
                WlbScheduledTask task = TaskFromItem(htInfo.Item);
                EditTask(task);
            }
        }

        private void lvTaskList_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
        {
            if (!_initializing)
            {
                if (e.ColumnIndex < minimumColumnWidths.Length)
                {
                    if (lvTaskList.Columns[e.ColumnIndex].Width < minimumColumnWidths[e.ColumnIndex])
                    {
                        lvTaskList.Columns[e.ColumnIndex].Width = minimumColumnWidths[e.ColumnIndex];
                    }
                }
                FixColumnWidths();
            }
        }

        private void lvTaskList_Resize(object sender, EventArgs e)
        {
            if (!_initializing)
            {
                FixColumnWidths();
            }
        }       

        private void lvTaskList_MouseDown(object sender, MouseEventArgs e)
        {
            //Check to see if this is a right-click event
            if (e.Button == MouseButtons.Right)
            {
                //determine which item was clicked
                ListViewHitTestInfo htInfo = lvTaskList.HitTest(e.Location);
                if (null != htInfo.Item)
                {
                    //make sure the right-clicked item is selected
                    // (right-clicking does not always select the item, which makes 
                    // usage a little clunky)
                    htInfo.Item.Selected = true;
                    //create the context menu and figure out which item(s) to show
                    MenuItem enableTask;
                    WlbScheduledTask task = TaskFromItem(htInfo.Item);                    
                    
                    ContextMenu menu = new ContextMenu();
                    if (task.Enabled)
                    {
                        enableTask = new MenuItem(Messages.DISABLE, EnableTask_Click);

                    }
                    else
                    {
                        enableTask = new MenuItem(Messages.ENABLE, EnableTask_Click);
                    }
                    menu.MenuItems.Add(enableTask);
                    menu.Show(lvTaskList, e.Location);
                }
            }           
            
        }

        private void lvTaskList_EnabledChanged(object sender, EventArgs e)
        {
            if (lvTaskList.Enabled)
            {
                InitializeControls(); 
            }
            else
            {
                lvTaskList.Items.Clear();
            }
        }

        private void weekView1_OnTriggerPointClick(object sender, MouseEventArgs e)
        {
            if (weekView1.SelectedTriggerPoint != null)
            {
                SelectTask((int)weekView1.SelectedTriggerPoint.Tag);
            }
        }

        private void weekView1_OnTriggerPointDoubleClick(object sender, MouseEventArgs e)
        {
            if (weekView1.SelectedTriggerPoint != null)
            {
                WlbScheduledTask task = _scheduledTasks.TaskList[weekView1.SelectedTriggerPoint.Tag.ToString()];
                if (null != task)
                {
                    EditTask(task);
                }
            }
        }

        #endregion

        #region ListView Sorting

        private class ListViewItemComparer : System.Collections.IComparer
        {
            private int col;
            public ListViewItemComparer()
            {
                col = 0;
            }
            public ListViewItemComparer(int column)
            {
                col = column;
            }
            public int Compare(object x, object y)
            {
                return CompareDouble(double.Parse(((ListViewItem)x).Text), double.Parse(((ListViewItem)y).Text));
                //WlbScheduledTask taskX = (WlbScheduledTask)((ListViewItem)x).Tag;
                //WlbScheduledTask taskY = (WlbScheduledTask)((ListViewItem)y).Tag;

                //int returnVal = -1;
                //returnVal = CompareInt((int)taskX.DaysOfWeek, (int)taskY.DaysOfWeek);

                //if (returnVal == 0)
                //{
                //    returnVal = CompareDouble(taskX.ExecuteTime.TimeOfDay.TotalMinutes, taskY.ExecuteTime.TimeOfDay.TotalMinutes);
                //}
                //return returnVal;
            }
            
            private int CompareDouble(double x, double y)
            {
                if (x < y)
                {
                    return -1;
                }
                else
                {
                    if (x == y)
                    {
                        return 0;
                    }
                    else
                    {
                        return 1;
                    }
                }
            }
            private int CompareInt(int x, int y)
            {
                if (x < y)
                {
                    return -1;
                }
                else
                {
                    if (x == y)
                    {
                        return 0;
                    }
                    else
                    {
                        return 1;
                    }
                }
            }
        }
#endregion

        //private void lvTaskList_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        //{
        //    if(e.IsSelected)
        //        SelectTask(TaskFromItem(e.Item).TaskId);            
        //}
        
    }
}
