using System;
using System.Globalization;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using System.Collections.Generic;
using System.Linq;
using KeePassLib;
using KeePassLib.Security;
using KeePassLib.Utility;

namespace keepass2android
{
	/// <summary>
	/// Interface for data stored in an intent or bundle as extra string
	/// </summary>
	public interface IExtra
	{
		/// <summary>
		/// put data to a bundle by calling one of the PutXX methods
		/// </summary>
		void ToBundle(Bundle b);

		/// <summary>
		/// Put data to an intent by calling PutExtra
		/// </summary>
		void ToIntent(Intent i);
	}

	/// <summary>
	/// represents data stored in an intent or bundle as extra string
	/// </summary>
	public class StringExtra: IExtra
	{
		public string Key { get; set; }
		public string Value{ get; set; }

		#region IExtra implementation

		public void ToBundle(Bundle b)
		{
			b.PutString(Key, Value);
		}

		public void ToIntent(Intent i)
		{
			i.PutExtra(Key, Value);
		}

		#endregion
	}

	/// <summary>
	/// represents data stored in an intent or bundle as extra string array list
	/// </summary>
	public class StringArrayListExtra : IExtra
	{
		public string Key { get; set; }
		public IList<string> Value { get; set; }

		#region IExtra implementation

		public void ToBundle(Bundle b)
		{
			b.PutStringArrayList(Key, Value);
		}

		public void ToIntent(Intent i)
		{
			i.PutStringArrayListExtra(Key, Value);
		}

		#endregion
	}

	/// <summary>
	/// represents data stored in an intent or bundle as extra int
	/// </summary>
	public class IntExtra: IExtra
	{
		public string Key { get; set; }
		public int Value{ get; set; }

		#region IExtra implementation

		public void ToBundle(Bundle b)
		{
			b.PutInt(Key, Value);
		}

		public void ToIntent(Intent i)
		{
			i.PutExtra(Key, Value);
		}

		#endregion
	}

	/// <summary>
	/// represents data stored in an intent or bundle as extra bool
	/// </summary>
	public class BoolExtra: IExtra
	{
		public string Key { get; set; }
		public bool Value{ get; set; }

		#region IExtra implementation

		public void ToBundle(Bundle b)
		{
			b.PutBoolean(Key, Value);
		}

		public void ToIntent(Intent i)
		{
			i.PutExtra(Key, Value);
		}

		#endregion
	}


	/// <summary>
	/// represents data stored in an intent or bundle as extra string array
	/// </summary>
	public class StringArrayExtra : IExtra
	{
		public string Key { get; set; }
		public string[] Value { get; set; }

		#region IExtra implementation

		public void ToBundle(Bundle b)
		{
			b.PutStringArray(Key, Value);
		}

		public void ToIntent(Intent i)
		{
			i.PutExtra(Key, Value);
		}

		#endregion
	}

	/// <summary>
	/// base class for "tasks": these are things the user wants to do and which require several activities
	/// </summary>
	/// Therefore AppTasks need to be serializable to bundles and intents to "survive" saving to instance state and changing activities.
	/// An AppTask has a type and may have several parameters ("extras").
	/// Activities call the task at special points so tasks can change the behaviour at these points.
	public abstract class AppTask
	{
		/// <summary>
		/// Loads the parameters of the task from the given bundle
		/// </summary>
		public virtual void Setup(Bundle b)
		{}

		/// <summary>
		/// Returns the parameters of the task for storage in a bundle or intent
		/// </summary>
		/// <value>The extras.</value>
		public virtual IEnumerable<IExtra> Extras { 
			get
			{
				yield break;
			}
		}

		public virtual void AfterUnlockDatabase(PasswordActivity act)
		{
			GroupActivity.Launch(act, this);
		}

		public virtual void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
		{
		}

		
		public virtual void PrepareNewEntry(PwEntry newEntry)
		{
			
		}
		
		public const String AppTaskKey = "KP2A_APPTASK";

		/// <summary>
		/// Should be used in OnCreate to (re)create a task
		/// if savedInstanceState is not null, the task is recreated from there. Otherwise it's taken from the intent.
		/// </summary>
		public static AppTask GetTaskInOnCreate(Bundle savedInstanceState, Intent intent)
		{
			AppTask task;
			if (savedInstanceState != null)
			{
				task = CreateFromBundle(savedInstanceState);
			}
			else
			{
				task = CreateFromIntent(intent);
			}
			Kp2aLog.Log("Loaded task " + task);
			return task;
		}

		public static AppTask CreateFromIntent(Intent i)
		{
			return CreateFromBundle(i.Extras);
		}

		public static AppTask CreateFromBundle(Bundle b)
		{
			return CreateFromBundle(b, new NullTask());
		}

		public static AppTask CreateFromBundle(Bundle b, AppTask failureReturn)
		{
			if (b == null)
				return failureReturn;

			string taskType = b.GetString(AppTaskKey);

			if (string.IsNullOrEmpty(taskType))
				return failureReturn;

			try
			{
			    Type type = Type.GetType("keepass2android." + taskType);
                if (type == null)
                    return failureReturn;
				AppTask task = (AppTask)Activator.CreateInstance(type);
				task.Setup(b);
				return task;
			}
			catch (Exception e)
			{
				Kp2aLog.Log("Cannot convert " + taskType + " in task: " + e);
				return failureReturn;
			}

		}

		/// <summary>
		/// Adds the extras of the task to the intent
		/// </summary>
		public void ToIntent(Intent intent)
		{
			GetTypeExtra(GetType()).ToIntent(intent);

			foreach (IExtra extra in Extras)
			{
				extra.ToIntent(intent);
			}
		}

		/// <summary>
		/// Adds the extras of the task to the bundle
		/// </summary>
		public void ToBundle(Bundle bundle)
		{
			GetTypeExtra(GetType()).ToBundle(bundle);

			foreach (IExtra extra in Extras)
			{
				extra.ToBundle(bundle);
			}

		}

		/// <summary>
		/// Returns an IExtra which must be part of the Extras of a task to describe the type
		/// </summary>
		static IExtra GetTypeExtra(Type type)
		{
			return new StringExtra { Key=AppTaskKey, Value=type.Name};
		}

		public virtual void StartInGroupActivity(GroupBaseActivity groupBaseActivity)
		{
		}

		public virtual void SetupGroupBaseActivityButtons(GroupBaseActivity groupBaseActivity)
		{
			groupBaseActivity.SetupNormalButtons();
		}

		public void SetActivityResult(Activity activity, Result result)
		{
			Intent data = new Intent();
			ToIntent(data);
			activity.SetResult(result, data);
		}

		/// <summary>
		/// Tries to extract the task from the data given as an Intent object in OnActivityResult. If successful, the task is assigned,
		/// otherwise, false is returned.
		/// </summary>
		public static bool TryGetFromActivityResult(Intent data, ref AppTask task)
		{
			if (data == null)
			{
				Kp2aLog.Log("TryGetFromActivityResult: no data");
				return false;
			}
			AppTask tempTask = CreateFromBundle(data.Extras, null);
			if (tempTask == null)
			{
				Kp2aLog.Log("No AppTask in OnActivityResult");
				return false;
			}
			
			task = tempTask;
			Kp2aLog.Log("AppTask " +task+" in OnActivityResult");
			return true;
		}

		protected void RemoveTaskFromIntent(Activity act)
		{
			if (act.Intent != null)
				act.Intent.RemoveExtra(AppTaskKey);

		}

		public virtual void CompleteOnCreateEntryActivity(EntryActivity activity)
		{
			activity.StartNotificationsService(false);
		}

		virtual public void PopulatePasswordAccessServiceIntent(Intent intent)
		{
			
		}
	}

	/// <summary>
	/// Implementation of AppTask for "no task currently active" (Null pattern)
	/// </summary>
	public class NullTask: AppTask
	{

	}

	/// <summary>
	/// User is about to search an entry for a given URL
	/// </summary>
	/// Derive from SelectEntryTask. This means that as soon as an Entry is opened, we're returning with
	/// ExitAfterTaskComplete. This also allows te specify the flag if we need to display the user notifications.
	public class SearchUrlTask: SelectEntryTask
	{
		public const String UrlToSearchKey = "UrlToSearch";

		public string UrlToSearchFor
		{
			get;
			set;
		}

		public override void Setup(Bundle b)
		{
			base.Setup(b);
			UrlToSearchFor = b.GetString(UrlToSearchKey);
		}
		public override IEnumerable<IExtra> Extras 
		{ 
			get
			{
				foreach (IExtra e in base.Extras)
					yield return e;
				yield return new StringExtra { Key=UrlToSearchKey, Value = UrlToSearchFor };
			}
		}
		public override void AfterUnlockDatabase(PasswordActivity act)
		{
			if (String.IsNullOrEmpty(UrlToSearchFor))
			{
				GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications =  ShowUserNotifications});
			}
			else
			{
				ShareUrlResults.Launch(act, this);
			}
			

			//removed. this causes an issue in the following workflow:
			//When the user wants to find an entry for a URL but has the wrong database open he needs 
			//to switch to another database. But the Task is removed already the first time when going through PasswordActivity 
			// (with the wrong db).
			//Then after switching to the right database, the task is gone.

			//A reason this code existed was the following workflow:
			//Using Chrome browser (with NEW_TASK flag for ActionSend): Share URL -> KP2A.
			//Now the AppTask was in PasswordActivity and didn't get out of it.
			//This is now solved by returning new tasks in ActivityResult.

			//RemoveTaskFromIntent(act);
			//act.AppTask = new NullTask();
		}

		public override void PopulatePasswordAccessServiceIntent(Intent intent)
		{
			base.PopulatePasswordAccessServiceIntent(intent);
			intent.PutExtra(UrlToSearchKey, UrlToSearchFor);
		}
	}

	
	/// <summary>
	/// User is about to select an entry for use in another app
	/// </summary>
	public class SelectEntryTask: AppTask
	{
		public SelectEntryTask()
		{
			ShowUserNotifications = true;
			CloseAfterCreate = true;
		}

		public const String ShowUserNotificationsKey = "ShowUserNotifications";

		public bool ShowUserNotifications { get; set; }

		public const String CloseAfterCreateKey = "CloseAfterCreate";

		public bool CloseAfterCreate { get; set; }


		public override void Setup(Bundle b)
		{
			ShowUserNotifications = GetBoolFromBundle(b, ShowUserNotificationsKey, true);
			CloseAfterCreate = GetBoolFromBundle(b, CloseAfterCreateKey, true);
		}

		private static bool GetBoolFromBundle(Bundle b, string key, bool defaultValue)
		{
			bool boolValue;
			if (!Boolean.TryParse(b.GetString(key), out boolValue))	
			{
				boolValue = defaultValue; 
			}
			return boolValue;
		}

		public override IEnumerable<IExtra> Extras
		{
			get
			{
				yield return new StringExtra { Key = ShowUserNotificationsKey, Value = ShowUserNotifications.ToString() };
				yield return new StringExtra { Key = CloseAfterCreateKey, Value = CloseAfterCreate.ToString() };
			}
		}

		public override void CompleteOnCreateEntryActivity(EntryActivity activity)
		{
			if (ShowUserNotifications)
			{
				//show the notifications
				activity.StartNotificationsService(CloseAfterCreate);
			}
			else
			{
				//to avoid getting into inconsistent state (LastOpenedEntry and Notifications): clear notifications:
				CopyToClipboardService.CancelNotifications(activity);
			}
			if (CloseAfterCreate)
			{
				//close
				activity.CloseAfterTaskComplete();	
			}
		}
	}

	/// <summary>
	/// User is about to select an entry. When selected, ask whether the url he was searching for earlier should be stored 
	/// in the selected entry for later use.
	/// </summary>
	public class SelectEntryForUrlTask: SelectEntryTask
	{
		/// <summary>
		/// default constructor for creating from Bundle
		/// </summary>
		public SelectEntryForUrlTask()
		{
			
		}

		public SelectEntryForUrlTask(string url)
		{
			UrlToSearchFor = url;
			ShowUserNotifications = true;
		}

		public const String UrlToSearchKey = "UrlToSearch";
		
		public string UrlToSearchFor
		{
			get;
			set;
		}

		public override void Setup(Bundle b)
		{
			base.Setup(b);
			UrlToSearchFor = b.GetString(UrlToSearchKey);
		}
		public override IEnumerable<IExtra> Extras
		{
			get
			{
				foreach (IExtra e in base.Extras)
					yield return e;
				yield return new StringExtra { Key = UrlToSearchKey, Value = UrlToSearchFor };
			}
		}

		public override void CompleteOnCreateEntryActivity(EntryActivity activity)
		{
			//if the database is readonly (or no URL exists), don't offer to modify the URL
			if ((App.Kp2a.GetDb().CanWrite == false) || (String.IsNullOrEmpty(UrlToSearchFor)))
			{
				base.CompleteOnCreateEntryActivity(activity);
				return;
			}


			AskAddUrlThenCompleteCreate(activity, UrlToSearchFor);

		}

		/// <summary>
		/// brings up a dialog asking the user whether he wants to add the given URL to the entry for automatic finding
		/// </summary>
		public void AskAddUrlThenCompleteCreate(EntryActivity activity, string url)
		{
			AlertDialog.Builder builder = new AlertDialog.Builder(activity);
			builder.SetTitle(activity.GetString(Resource.String.AddUrlToEntryDialog_title));

			builder.SetMessage(activity.GetString(Resource.String.AddUrlToEntryDialog_text, new Java.Lang.Object[] { url }));

			builder.SetPositiveButton(activity.GetString(Resource.String.yes), (dlgSender, dlgEvt) =>
			{
				activity.AddUrlToEntry(url, () => base.CompleteOnCreateEntryActivity(activity));
			});

			builder.SetNegativeButton(activity.GetString(Resource.String.no), (dlgSender, dlgEvt) =>
			{
				base.CompleteOnCreateEntryActivity(activity);
			});

			Dialog dialog = builder.Create();
			dialog.Show();
		}
		
	}


	/// <summary>
	/// User is about to move entries and/or groups to another group
	/// </summary>
	public class MoveElementsTask: AppTask
	{
		public const String UuidsKey = "MoveElement_Uuids";

		public IEnumerable<PwUuid> Uuids
		{
			get;
			set;
		}

		public override void Setup(Bundle b)
		{
		    Uuids = b.GetString(UuidsKey).Split(';')
               .Where(s => !String.IsNullOrEmpty(s)) 
               .Select(stringPart => new PwUuid(MemUtil.HexStringToByteArray(stringPart)))
               .ToList(); //property might be accessed several times, avoid parsing each time
		}

	    public override IEnumerable<IExtra> Extras
	    {
	        get
	        {
	            yield return new StringExtra
	            {
	                Key = UuidsKey,
	                Value = Uuids.Select(uuid => MemUtil.ByteArrayToHexString(uuid.UuidBytes))
	                    .Aggregate((a, b) => a + ";" + b)
	            };
	        } 
	    }
	
		public override void StartInGroupActivity(GroupBaseActivity groupBaseActivity)
		{
			base.StartInGroupActivity(groupBaseActivity);
			groupBaseActivity.StartMovingElements();
		}
		public override void SetupGroupBaseActivityButtons(GroupBaseActivity groupBaseActivity)
		{
			groupBaseActivity.ShowInsertElementsButtons();
		}
	}

	
	/// <summary>
	/// User is about to create a new entry. The task might already "know" some information about the contents.
	/// </summary>
	public class CreateEntryThenCloseTask: AppTask
	{
		public CreateEntryThenCloseTask()
		{
			ShowUserNotifications = true;
		}

		/// <summary>
		/// extra key if only a URL is passed. optional.
		/// </summary>
		public const String UrlKey = "CreateEntry_Url";
		
		/// <summary>
		/// extra key if a json serialized key/value mapping is passed. optional.
		/// </summary>
		/// Uses the PluginSDKs keys because this is mainly used for communicating with plugins.
		/// Of course the data might also contain "non-output-data" (e.g. placeholders), but usually won't.
		public const String AllFieldsKey = Keepass2android.Pluginsdk.Strings.ExtraEntryOutputData;

		/// <summary>
		/// extra key to specify a list of protected field keys in AllFieldsKey. Passed as StringArrayExtra. optional.
		/// </summary>
		public const String ProtectedFieldsListKey = Keepass2android.Pluginsdk.Strings.ExtraProtectedFieldsList;


		/// <summary>
		/// Extra key to specify whether user notifications (e.g. for copy password or keyboard) should be displayed when the entry 
		/// is selected after creating.
		/// </summary>
		public const String ShowUserNotificationsKey = "ShowUserNotifications";


		public string Url { get; set; }

		public string AllFields { get; set; }

		public IList<string> ProtectedFieldsList { get; set; }

		public bool ShowUserNotifications { get; set; }


		public override void Setup(Bundle b)
		{
			bool showUserNotification; 
			if (!Boolean.TryParse(b.GetString(ShowUserNotificationsKey), out showUserNotification))
			{
				showUserNotification = true; //default to true
			}
			ShowUserNotifications = showUserNotification;
			
			Url = b.GetString(UrlKey);
			AllFields = b.GetString(AllFieldsKey);
			ProtectedFieldsList = b.GetStringArrayList(ProtectedFieldsListKey);
		}
		public override IEnumerable<IExtra> Extras 
		{ 
			get
			{
				if (Url != null)
					yield return new StringExtra { Key = UrlKey, Value = Url };
				if (AllFields != null)
					yield return new StringExtra { Key = AllFieldsKey, Value = AllFields };
				if (ProtectedFieldsList != null)
					yield return new StringArrayListExtra { Key = ProtectedFieldsListKey, Value = ProtectedFieldsList };
				
				yield return new StringExtra { Key = ShowUserNotificationsKey, Value = ShowUserNotifications.ToString() };
			}
		}
		
		
		public override void PrepareNewEntry(PwEntry newEntry)
		{
			if (Url != null)
			{
				newEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, Url));
			}
			if (AllFields != null)
			{
				
				var allFields = new Org.Json.JSONObject(AllFields);
				for (var iter = allFields.Keys(); iter.HasNext; )
				{
					string key = iter.Next().ToString();
					string value = allFields.Get(key).ToString();
					bool isProtected = ((ProtectedFieldsList != null) && (ProtectedFieldsList.Contains(key))) 
						|| (key == PwDefs.PasswordField);
					newEntry.Strings.Set(key, new ProtectedString(isProtected, value));
				}
				
			}
					
		}

		public override void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
		{
			EntryActivity.Launch(entryEditActivity, newEntry, -1, 
				new SelectEntryTask { ShowUserNotifications = this.ShowUserNotifications}, 
				ActivityFlags.ForwardResult);
			//no need to call Finish here, that's done in EntryEditActivity ("closeOrShowError")	
		}
		
		public override void CompleteOnCreateEntryActivity(EntryActivity activity)
		{
			//if the user selects an entry before creating the new one, we're not closing the app
			base.CompleteOnCreateEntryActivity(activity);
		}
	}


	/// <summary>
	/// Navigate to a folder and open a Task (appear in SearchResult)
	/// </summary>
	public abstract class NavigateAndLaunchTask: AppTask
	{
		// All group Uuid are stored in guuidKey + indice
		// The last one is the destination group 
		public const String NumberOfGroupsKey = "NumberOfGroups";
		public const String GUuidKey = "gUuidKey"; 
		public const String FullGroupNameKey = "fullGroupNameKey";
		public const String ToastEnableKey = "toastEnableKey";

		#if INCLUDE_DEBUG_MOVE_GROUPNAME
		public const String gNameKey = "gNameKey";
		private LinkedList<string> groupNameList;
		#endif

		private LinkedList<string> _groupUuid;
		protected AppTask TaskToBeLaunchedAfterNavigation;

		protected String FullGroupName {
			get ;
			set ;
		}

		protected bool ToastEnable {
			get;
			set;
		}

		protected NavigateAndLaunchTask() {
			TaskToBeLaunchedAfterNavigation = new NullTask();
			FullGroupName = "";
			ToastEnable = false;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="keepass2android.NavigateAndLaunchTask"/> class.
		/// </summary>
		/// <param name="groups">Groups.</param>
		/// <param name="taskToBeLaunchedAfterNavigation">Task to be launched after navigation.</param>
		/// <param name="toastEnable">If set to <c>true</c>, toast will be displayed after navigation.</param>
		protected NavigateAndLaunchTask(PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
			TaskToBeLaunchedAfterNavigation = taskToBeLaunchedAfterNavigation;
			PopulateGroups (groups);
			ToastEnable = toastEnable;
		}

		public void PopulateGroups(PwGroup groups) {

			_groupUuid = new LinkedList<String>();

			#if INCLUDE_DEBUG_MOVE_GROUPNAME
			groupNameList = new LinkedList<String>{};
			#endif

			FullGroupName = "";
			PwGroup readGroup = groups;
			while (readGroup != null) {

				if ( (readGroup.ParentGroup != null) || 
					(readGroup.ParentGroup == null) && (readGroup == groups) ) {
					FullGroupName = readGroup.Name + "." + FullGroupName;
				}

				_groupUuid.AddFirst (MemUtil.ByteArrayToHexString (readGroup.Uuid.UuidBytes));

				#if INCLUDE_DEBUG_MOVE_GROUPNAME
				groupNameList.AddFirst (readGroup.Name);
				#endif

				readGroup = readGroup.ParentGroup;

			}

		}


		/// <summary>
		/// Loads the parameters of the task from the given bundle. Embeded task is not setup from this bundle
		/// </summary>
		/// <param name="b">The bundle component.</param>
		public override void Setup(Bundle b)
		{
			int numberOfGroups = b.GetInt(NumberOfGroupsKey);

			_groupUuid = new LinkedList<String>();
			#if INCLUDE_DEBUG_MOVE_GROUPNAME 
			groupNameList = new LinkedList<String>{};
			#endif 

			int i = 0;

			while (i < numberOfGroups) {

				_groupUuid.AddLast ( b.GetString (GUuidKey + i) ) ;

				#if INCLUDE_DEBUG_MOVE_GROUPNAME 
				groupNameList.AddLast ( b.GetString (gNameKey + i);
				#endif 
				i++;
			}

			FullGroupName = b.GetString (FullGroupNameKey);
			ToastEnable = b.GetBoolean (ToastEnableKey);
				
		}

		public override IEnumerable<IExtra> Extras
		{
			get
			{
				// Return Navigate group Extras
				IEnumerator<String> eGroupKeys = _groupUuid.GetEnumerator ();

				#if INCLUDE_DEBUG_MOVE_GROUPNAME
				IEnumerator<String> eGroupName = groupNameList.GetEnumerator ();
				#endif

				int i = 0;
				while (eGroupKeys.MoveNext()) {
					yield return new StringExtra { Key = GUuidKey + i.ToString (CultureInfo.InvariantCulture), Value = eGroupKeys.Current };

					#if INCLUDE_DEBUG_MOVE_GROUPNAME
					eGroupName.MoveNext();
					yield return new StringExtra { Key = gNameKey + i.ToString (), Value = eGroupName.Current };
					#endif

					i++;
				}

				yield return new IntExtra{ Key = NumberOfGroupsKey, Value = i };
				yield return new StringExtra{ Key = FullGroupNameKey, Value = FullGroupName };
				yield return new BoolExtra{ Key = ToastEnableKey, Value = ToastEnable };

				// Return afterTaskExtras
				foreach (var extra in TaskToBeLaunchedAfterNavigation.Extras)
				{
					yield return extra;
				}

			}
		}

		public override void StartInGroupActivity(GroupBaseActivity groupBaseActivity)
		{
			base.StartInGroupActivity(groupBaseActivity);

			if (GroupIsFound(groupBaseActivity) ){ // Group has been found: display toaster and stop here

				if (ToastEnable) {
					String toastMessage = groupBaseActivity.GetString (Resource.String.NavigationToGroupCompleted_message, new Java.Lang.Object[] { FullGroupName});
					
					Toast.MakeText (groupBaseActivity, toastMessage, ToastLength.Long).Show ();
				}
				
				groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation);
				return;

			} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to go up in groups tree

				// Get next Group Uuid
				var linkedListNode = _groupUuid.Find(groupBaseActivity.UuidGroup);
				if (linkedListNode != null)
				{
					//Note: Resharper says there is a possible NullRefException.
					//This is not the case because it was checked above if we're already there or not.
					String nextGroupUuid = linkedListNode.Next.Value;
					PwUuid nextGroupPwUuid = new PwUuid (MemUtil.HexStringToByteArray (nextGroupUuid));

					// Create Group Activity
					PwGroup nextGroup = App.Kp2a.GetDb ().Groups [nextGroupPwUuid];
					GroupActivity.Launch (groupBaseActivity, nextGroup, this);
				}
				return;

			} else { // Need to go down in groups tree
				SetActivityResult(groupBaseActivity, KeePass.ExitNormal);
				groupBaseActivity.Finish();

			} 

		}
		public override void SetupGroupBaseActivityButtons(GroupBaseActivity groupBaseActivity)
		{
			
		}

		public bool GroupIsFound(GroupBaseActivity groupBaseActivity)
		{
			return _groupUuid.Last.Value.Equals (groupBaseActivity.UuidGroup);
		}
	}

	public class NavigateToFolder: NavigateAndLaunchTask {

		public NavigateToFolder()
		{
		}

		public NavigateToFolder(PwGroup groups, bool toastEnable = false)
			: base(groups, new NullTask(), toastEnable) 
		{
		}

	}

	public class NavigateToFolderAndLaunchMoveElementTask: NavigateAndLaunchTask {
	
		public NavigateToFolderAndLaunchMoveElementTask()
		{

		}


		public NavigateToFolderAndLaunchMoveElementTask(PwGroup groups, List<PwUuid> uuids, bool toastEnable = false)
			:base(groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
		}

		public override void Setup(Bundle b) {
			base.Setup(b);

			TaskToBeLaunchedAfterNavigation = new MoveElementsTask ();
			TaskToBeLaunchedAfterNavigation.Setup (b);

		}


	}

}

