/**
 * Copyright (c) 2013, Redsolution LTD. All rights reserved.
 * 
 * This file is part of Xabber project; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License, Version 3.
 * 
 * Xabber is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License,
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */
package com.xabber.android.ui.helper;

import android.support.v4.app.FragmentActivity;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.SubMenu;

import com.xabber.android.data.Application;
import com.xabber.android.data.NetworkException;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.account.AccountItem;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.account.StatusMode;
import com.xabber.android.data.connection.ConnectionState;
import com.xabber.android.data.extension.muc.MUCManager;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.notification.NotificationManager;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.data.roster.GroupManager;
import com.xabber.android.data.roster.PresenceManager;
import com.xabber.android.data.roster.ShowOfflineMode;
import com.xabber.android.ui.preferences.AccountEditor;
import com.xabber.android.ui.ChatViewer;
import com.xabber.android.ui.ContactAdd;
import com.xabber.android.ui.ContactEditor;
import com.xabber.android.ui.preferences.ContactViewer;
import com.xabber.android.ui.MUCEditor;
import com.xabber.android.ui.StatusEditor;
import com.xabber.android.ui.adapter.UpdatableAdapter;
import com.xabber.android.ui.dialog.ContactDeleteDialogFragment;
import com.xabber.android.ui.dialog.GroupDeleteDialogFragment;
import com.xabber.android.ui.dialog.GroupRenameDialogFragment;
import com.xabber.android.ui.dialog.MUCDeleteDialogFragment;
import com.xabber.androiddev.R;

/**
 * Helper class for context menu creation.
 * 
 * @author alexander.ivanov
 * 
 */
public class ContextMenuHelper {

	private ContextMenuHelper() {
	}

	public static void createContactContextMenu(
			final FragmentActivity activity, final UpdatableAdapter adapter,
			AbstractContact abstractContact, ContextMenu menu) {
		final String account = abstractContact.getAccount();
		final String user = abstractContact.getUser();
		menu.setHeaderTitle(abstractContact.getName());
		menu.add(R.string.chat_viewer).setOnMenuItemClickListener(
				new MenuItem.OnMenuItemClickListener() {

					@Override
					public boolean onMenuItemClick(MenuItem item) {
						MessageManager.getInstance().openChat(account, user);
						activity.startActivity(ChatViewer.createIntent(
								activity, account, user));
						return true;
					}
				});
		if (MUCManager.getInstance().hasRoom(account, user)) {
			if (!MUCManager.getInstance().inUse(account, user))
				menu.add(R.string.muc_edit).setIntent(
						MUCEditor.createIntent(activity, account, user));
			menu.add(R.string.muc_delete).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							MUCDeleteDialogFragment.newInstance(account, user)
									.show(activity.getSupportFragmentManager(),
											"MUC_DELETE");
							return true;
						}

					});
			if (MUCManager.getInstance().isDisabled(account, user))
				menu.add(R.string.muc_join).setOnMenuItemClickListener(
						new MenuItem.OnMenuItemClickListener() {

							@Override
							public boolean onMenuItemClick(MenuItem item) {
								MUCManager.getInstance().joinRoom(account,
										user, true);
								return true;
							}

						});
			else
				menu.add(R.string.muc_leave).setOnMenuItemClickListener(
						new MenuItem.OnMenuItemClickListener() {

							@Override
							public boolean onMenuItemClick(MenuItem item) {
								MUCManager.getInstance().leaveRoom(account,
										user);
								MessageManager.getInstance().closeChat(account,
										user);
								NotificationManager.getInstance()
										.removeMessageNotification(account,
												user);
								adapter.onChange();
								return true;
							}

						});
		} else {
			menu.add(R.string.contact_viewer).setIntent(
					ContactViewer.createIntent(activity, account, user));
			menu.add(R.string.contact_editor).setIntent(
					ContactEditor.createIntent(activity, account, user));
			menu.add(R.string.contact_delete).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							ContactDeleteDialogFragment.newInstance(account,
									user).show(
									activity.getSupportFragmentManager(),
									"CONTACT_DELETE");
							return true;
						}

					});
			if (MessageManager.getInstance().hasActiveChat(account, user))
				menu.add(R.string.close_chat).setOnMenuItemClickListener(
						new MenuItem.OnMenuItemClickListener() {

							@Override
							public boolean onMenuItemClick(MenuItem item) {
								MessageManager.getInstance().closeChat(account,
										user);
								NotificationManager.getInstance()
										.removeMessageNotification(account,
												user);
								adapter.onChange();
								return true;
							}

						});
			if (abstractContact.getStatusMode() == StatusMode.unsubscribed)
				menu.add(R.string.request_subscription)
						.setOnMenuItemClickListener(
								new MenuItem.OnMenuItemClickListener() {

									@Override
									public boolean onMenuItemClick(MenuItem item) {
										try {
											PresenceManager.getInstance()
													.requestSubscription(
															account, user);
										} catch (NetworkException e) {
											Application.getInstance()
													.onError(e);
										}
										return true;
									}

								});
		}
		if (PresenceManager.getInstance().hasSubscriptionRequest(account, user)) {
			menu.add(R.string.accept_subscription).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							try {
								PresenceManager.getInstance()
										.acceptSubscription(account, user);
							} catch (NetworkException e) {
								Application.getInstance().onError(e);
							}
							activity.startActivity(ContactEditor.createIntent(
									activity, account, user));
							return true;
						}

					});
			menu.add(R.string.discard_subscription).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							try {
								PresenceManager.getInstance()
										.discardSubscription(account, user);
							} catch (NetworkException e) {
								Application.getInstance().onError(e);
							}
							return true;
						}

					});
		}
	}

	public static void createGroupContextMenu(final FragmentActivity activity,
			UpdatableAdapter adapter, final String account, final String group,
			ContextMenu menu) {
		menu.setHeaderTitle(GroupManager.getInstance().getGroupName(account,
				group));
		if (group != GroupManager.ACTIVE_CHATS && group != GroupManager.IS_ROOM) {
			menu.add(R.string.group_rename).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							GroupRenameDialogFragment.newInstance(
									account == GroupManager.NO_ACCOUNT ? null
											: account,
									group == GroupManager.NO_GROUP ? null
											: group).show(
									activity.getSupportFragmentManager(),
									"GROUP_RENAME");
							return true;
						}
					});
			if (group != GroupManager.NO_GROUP)
				menu.add(R.string.group_remove).setOnMenuItemClickListener(
						new MenuItem.OnMenuItemClickListener() {

							@Override
							public boolean onMenuItemClick(MenuItem item) {
								GroupDeleteDialogFragment
										.newInstance(
												account == GroupManager.NO_ACCOUNT ? null
														: account, group)
										.show(activity
												.getSupportFragmentManager(),
												"GROUP_DELETE");
								return true;
							}
						});
		}
		createOfflineModeContextMenu(adapter, account, group, menu);
	}

	public static void createAccountContextMenu(
			final FragmentActivity activity, UpdatableAdapter adapter,
			final String account, ContextMenu menu) {
		menu.setHeaderTitle(AccountManager.getInstance()
				.getVerboseName(account));
		AccountItem accountItem = AccountManager.getInstance().getAccount(
				account);
		ConnectionState state = accountItem.getState();
		if (state == ConnectionState.waiting)
			menu.add(R.string.account_reconnect).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							if (AccountManager.getInstance()
									.getAccount(account).updateConnection(true))
								AccountManager.getInstance().onAccountChanged(
										account);
							return true;
						}

					});
		menu.add(R.string.status_editor).setIntent(
				StatusEditor.createIntent(activity, account));
		menu.add(R.string.account_editor).setIntent(
				AccountEditor.createIntent(activity, account));
		if (state.isConnected()) {
			menu.add(R.string.contact_viewer).setOnMenuItemClickListener(
					new MenuItem.OnMenuItemClickListener() {

						@Override
						public boolean onMenuItemClick(MenuItem item) {
							String user = AccountManager.getInstance()
									.getAccount(account).getRealJid();
							if (user == null)
								Application.getInstance().onError(
										R.string.NOT_CONNECTED);
							else {
								activity.startActivity(ContactViewer
										.createIntent(activity, account, user));
							}
							return true;
						}

					});
			menu.add(R.string.contact_add).setIntent(
					ContactAdd.createIntent(activity, account));
		}
		if (SettingsManager.contactsShowAccounts())
			createOfflineModeContextMenu(adapter, account, null, menu);
	}

	private static void createOfflineModeContextMenu(UpdatableAdapter adapter,
			String account, String group, ContextMenu menu) {
		SubMenu mapMode = menu.addSubMenu(R.string.show_offline_settings);
		mapMode.setHeaderTitle(R.string.show_offline_settings);
		MenuItem always = mapMode.add(R.string.show_offline_settings, 0, 0,
				R.string.show_offline_always).setOnMenuItemClickListener(
				new OfflineModeClickListener(adapter, account, group,
						ShowOfflineMode.always));
		MenuItem normal = mapMode.add(R.string.show_offline_settings, 0, 0,
				R.string.show_offline_normal).setOnMenuItemClickListener(
				new OfflineModeClickListener(adapter, account, group,
						ShowOfflineMode.normal));
		MenuItem never = mapMode.add(R.string.show_offline_settings, 0, 0,
				R.string.show_offline_never).setOnMenuItemClickListener(
				new OfflineModeClickListener(adapter, account, group,
						ShowOfflineMode.never));
		mapMode.setGroupCheckable(R.string.show_offline_settings, true, true);
		ShowOfflineMode showOfflineMode = GroupManager.getInstance()
				.getShowOfflineMode(account,
						group == null ? GroupManager.IS_ACCOUNT : group);
		if (showOfflineMode == ShowOfflineMode.always)
			always.setChecked(true);
		else if (showOfflineMode == ShowOfflineMode.normal)
			normal.setChecked(true);
		else if (showOfflineMode == ShowOfflineMode.never)
			never.setChecked(true);
		else
			throw new IllegalStateException();
	}

	private static class OfflineModeClickListener implements
			MenuItem.OnMenuItemClickListener {

		private final UpdatableAdapter adapter;
		private final String account;
		private final String group;
		private final ShowOfflineMode mode;

		public OfflineModeClickListener(UpdatableAdapter adapter,
				String account, String group, ShowOfflineMode mode) {
			super();
			this.adapter = adapter;
			this.account = account;
			this.group = group;
			this.mode = mode;
		}

		@Override
		public boolean onMenuItemClick(MenuItem item) {
			GroupManager.getInstance().setShowOfflineMode(account,
					group == null ? GroupManager.IS_ACCOUNT : group, mode);
			adapter.onChange();
			return true;
		}

	}

}
