using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;

namespace AddTaskListItems
{
	/// <summary>The object for implementing an Add-in.</summary>
	/// <seealso class='IDTExtensibility2' />
	public class Connect : IDTExtensibility2
	{
		/// <summary>Implements the constructor for the Add-in object. Place your initialization code within this method.</summary>
		public Connect()
		{
		}

		/// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
		/// <param term='application'>Root object of the host application.</param>
		/// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
		/// <param term='addInInst'>Object representing this Add-in.</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
		{
      EnvDTE.Window taskListWindow;
      EnvDTE.TaskList taskList;
      EnvDTE.TaskItems taskItems;

			_applicationObject = (DTE2)application;
			_addInInstance = (AddIn)addInInst;

      //Find the TaskItems object:
      taskListWindow = _applicationObject.Windows.Item(EnvDTE.Constants.vsWindowKindTaskList);
      taskList = (EnvDTE.TaskList)taskListWindow.Object;
      taskItems = taskList.TaskItems;

      //Add some tasks, using the different options available:
      taskItems.Add("TestCategory", "TestSubCategory", "Task Item with using minimum parameters", vsTaskPriority.vsTaskPriorityMedium, null, false, "", 0, true, true);
      taskItems.Add("TestCategory", "TestSubCategory", "Task Item with low priority", vsTaskPriority.vsTaskPriorityLow, null, false, "", 0, true, true);
      taskItems.Add("TestCategory", "TestSubCategory", "Task Item with low priority and a compiler error icon", vsTaskPriority.vsTaskPriorityLow, vsTaskIcon.vsTaskIconSquiggle, false, "", 0, true, true);
      taskItems.Add("TestCategory", "TestSubCategory", "Task Item with low priority, compiler error icon, and can be checked", vsTaskPriority.vsTaskPriorityLow, vsTaskIcon.vsTaskIconSquiggle, true, "", 0, true, true);
      taskItems.Add("TestCategory", "TestSubCategory", "Task Item with low priority, compiler error icon, can be checked, and has a file with a line number", vsTaskPriority.vsTaskPriorityLow, vsTaskIcon.vsTaskIconSquiggle, true, @"C:\SomeFile.txt", 2, true, true);
      taskItems.Add("TestCategory", "TestSubCategory", "Task Item with low priority, compiler error icon, can be checked, has a file with a line number, and cannot be deleted by the user", vsTaskPriority.vsTaskPriorityLow, vsTaskIcon.vsTaskIconSquiggle, true, @"C:\SomeFile.txt", 2, false, true);

      //Add 10 task items, waiting until all items are added before flushing them
      // out to the task list:
      for (int i = 1; i < 10; i++)
      {
        taskItems.Add("TestCategory", "TestSubCategory", "Task Item with using minimum parameters", vsTaskPriority.vsTaskPriorityMedium, null, false, "", 0, true, false);
      }
      taskItems.ForceItemsToTaskList();

      //Load an image for the custom bitmap for a new task item
      System.Drawing.Bitmap customTaskListIcon = Resource.CustomTaskListIcon;

      //Add a task that uses the custom bitmap:
      taskItems.Add("Category", "SubCatategory", "Description", vsTaskPriority.vsTaskPriorityLow, customTaskListIcon.GetHbitmap(), true, "", 0, true, true);

      //Connect to the Navigated event for the task so that when
      // a navigate is performed on a task item and the file and
      // line has been set, then we can open that file and move to 
      // the correct line number:
      taskListEvents = (EnvDTE.TaskListEvents)_applicationObject.Events.get_TaskListEvents("TestCategory");
      taskListEvents.TaskNavigated += new _dispTaskListEvents_TaskNavigatedEventHandler(this.TaskNavigated);
		}

		/// <summary>Implements the OnDisconnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being unloaded.</summary>
		/// <param term='disconnectMode'>Describes how the Add-in is being unloaded.</param>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
		{
      //Disconnect from the TaskNavigated event:
      taskListEvents.TaskNavigated -= new _dispTaskListEvents_TaskNavigatedEventHandler(this.TaskNavigated);
		}

		/// <summary>Implements the OnAddInsUpdate method of the IDTExtensibility2 interface. Receives notification when the collection of Add-ins has changed.</summary>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />		
		public void OnAddInsUpdate(ref Array custom)
		{
		}

		/// <summary>Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host application has completed loading.</summary>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnStartupComplete(ref Array custom)
		{
		}

		/// <summary>Implements the OnBeginShutdown method of the IDTExtensibility2 interface. Receives notification that the host application is being unloaded.</summary>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />
		public void OnBeginShutdown(ref Array custom)
		{
		}

    public void TaskNavigated(EnvDTE.TaskItem taskItem, ref bool navigateHandled)
    {
      //If the file argument has been specified for this task...
      if (taskItem.FileName != "")
      {
        EnvDTE.Window fileWindow;
        EnvDTE.TextWindow textWindow;
        EnvDTE.TextPane textPane;

        //Then open the file, find the TextWindow and TextPane objects...
        fileWindow = _applicationObject.ItemOperations.OpenFile(taskItem.FileName, EnvDTE.Constants.vsViewKindTextView);
        textWindow = (EnvDTE.TextWindow)fileWindow.Object;
        textPane = (EnvDTE.TextPane)textWindow.ActivePane;

        //Then move the caret to the correct line:
        textPane.Selection.MoveTo(taskItem.Line, 1, false);
        textPane.Selection.SelectLine();
        navigateHandled = true;
      }
    }
		
		private DTE2 _applicationObject;
		private AddIn _addInInstance;
    private EnvDTE.TaskListEvents taskListEvents;
	}
}