// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//   
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//   
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//  
// Authors:
//       Jan Rüegg <rggjan@gmail.com>
//       Gabriel Walch <walchg@student.ethz.ch>
//       Gerd Zellweger <mail@gerdzellweger.com>
// 

using System;
using System.Collections.Generic;

namespace Tomboy.TaskManager
{

	/// <summary>
	/// Traverses the tasks structure depth first for the average priority of the (direct and indirect) children of some task or tasklist
	/// The result can be either retrieved as Priority or Integer, rounded.
	/// If all lower level attributedtasks' priorities are unset, Priority.NORMAL is passed back
	/// </summary>
	public class GetAvPriorityVisitor : Visitor
	{

		private int set_ints;
		private double result;
		
		/// <summary>
		/// The result of the traversation as an integer
		/// </summary>
		public int IntResult {
			get {
				if (result == 0)
					return (int)Priority.NORMAL;
				
				double res = result/set_ints;
				int rounded = (int) Math.Round (res);
				return rounded;
			}
		}
		
		/// <summary>
		/// The result of the traversation as Priority instance
		/// </summary>
		public Priority Result {
			get {
				return (Priority) IntResult;
			}
		}
		
		public GetAvPriorityVisitor ()
		{
			result = 0;
			set_ints = 0;
			visited = new List<AttributedTask>();
		}
		
		public override void visit (Note note)
		{
			//Again, nothing here	
		}
		
		public override void visit (TaskList taskList)
		{
			//Tasklist do not have priorities. Ignore them
			visited.Add (taskList);
			foreach (Task task in taskList.Tasks)
				if (!visited.Contains (task))
					this.visit (task);
		}
		
		public override void visit (Task task)
		{
			visited.Add (task);
			
			if (task.Priority != Priority.UNSET){
				result += (int)task.Priority;
				set_ints += 1;
			}
			
			foreach (TaskList taskList in task.Subtasks)
				if (!visited.Contains (taskList))
					this.visit (taskList);
		}
	}
}
