package com.quantum.actions;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

import com.quantum.ImageStore;
import com.quantum.Messages;
import com.quantum.QuantumPlugin;
import com.quantum.model.Bookmark;
import com.quantum.model.BookmarkCollection;
import com.quantum.model.DisplayableComparator;
import com.quantum.sql.parser.SQLParser;
import com.quantum.view.SQLQueryView;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;

/**
 * Executes a query from the QueryView
 *
 * @author panic
 */
public class ExecuteAction extends BaseExecuteAction implements IMenuCreator {
	
private static final String LAST_USED_BOOKMARK_PREFERENCE = ExecuteAction.class.getName() + ".bookmark";
	private SQLQueryView view;
	
	public ExecuteAction(SQLQueryView view) {
		this.view = view;
		setActionDefinitionId("com.quantum.actions.ExecuteAction");
		setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.PLAY));
		initTextAndToolTip();
		setMenuCreator(this);
	}

	/**
	 * 
	 */
	private void initTextAndToolTip() {
		Bookmark lastUsedBookmark = getLastUsedBookmark();
		if (lastUsedBookmark == null) {
			setText(Messages.getString(ExecuteAction.class, "textNoBookmark"));
			setToolTipText(Messages.getString(ExecuteAction.class, "textNoBookmark"));
		} else {
			Object[] parameters = new Object[] { lastUsedBookmark.getName() };
			setText(Messages.getString(ExecuteAction.class, "text", parameters));
			setToolTipText(Messages.getString(ExecuteAction.class, "text", parameters));
		}
	}

	protected Bookmark getBookmark() {
		Bookmark lastUsedBookmark = getLastUsedBookmark();
		return lastUsedBookmark == null ? super.getBookmark() : lastUsedBookmark;
	}
	protected void execute(Bookmark bookmark, Connection connection) 
			throws IOException, CoreException, SQLException {
		
		try {
			boolean autoCommitPreference = this.view.isAutoCommitPreference();
			boolean changed = false;
			if (connection.getAutoCommit() != autoCommitPreference) {
				connection.setAutoCommit(autoCommitPreference);
				changed = true;
			}
			
			super.execute(bookmark, connection);
			
			if (changed) {
				MessageDialog.openInformation(getShell(), 
						Messages.getString(ExecuteAction.class, "autocommitTitle"), 
						Messages.getString(ExecuteAction.class, "autocommitMessage", 
								new Object[] { bookmark.getName() }));
			}
		} finally {
			QuantumPlugin.getDefault().getPreferenceStore().setValue(
					LAST_USED_BOOKMARK_PREFERENCE, bookmark.getName());
			initTextAndToolTip();
		}
	}
	/**
	 * @return
	 */
	protected List getQueries() {
		getStatusLineManager().setMessage(
				Messages.getString(ExecuteAction.class, "parsing")); //$NON-NLS-1$
		Vector queries = SQLParser.parse(view.getQuery());
		return queries;
	}

	/**
	 * @return
	 */
	protected IStatusLineManager getStatusLineManager() {
		return this.view.getViewSite().getActionBars().getStatusLineManager();
	}

	protected Shell getShell() {
		return this.view.getViewSite().getShell();
	}

	public void dispose() {
	}

	public Menu getMenu(Control parent) {
		Menu menu = new Menu(parent);
		/**
		 * Add listener to repopulate the menu each time
		 * it is shown because the list of bookmarks may have changed.
		 */
		menu.addMenuListener(new MenuAdapter() {
			public void menuShown(MenuEvent e) {
				Menu menu = (Menu)e.widget;
				MenuItem[] items = menu.getItems();
				for (int i=0; i < items.length; i++) {
					items[i].dispose();
				}
				fillMenu(menu);
			}
		});
		return menu;
	}

	public Menu getMenu(Menu parent) {
		// never called...
		return null;
	}

	protected void fillMenu(Menu menu) {
		Bookmark lastUsedBookmark = getLastUsedBookmark();
		
		if (lastUsedBookmark != null) {
			createSubAction(menu, lastUsedBookmark);
			Separator separator = new Separator();
			separator.fill(menu, -1);
		}
		
		Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
		Arrays.sort(bookmarks, new DisplayableComparator());
		for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
			final Bookmark bookmark = bookmarks[i];
			createSubAction(menu, bookmark);
		}
	}



	/**
	 * @return
	 */
	private Bookmark getLastUsedBookmark() {
		String lastUsedName = QuantumPlugin.getDefault().getPreferenceStore().getString(
				LAST_USED_BOOKMARK_PREFERENCE);
		Bookmark lastUsedBookmark = lastUsedName == null 
				? null 
				: BookmarkCollection.getInstance().find(lastUsedName);
		return lastUsedBookmark;
	}



	/**
	 * @param menu
	 * @param bookmark
	 */
	private void createSubAction(Menu menu, final Bookmark bookmark) {
		Action action = new Action() {
			public void run() {
				ExecuteAction.this.execute(bookmark);
			}
		};
		action.setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.BOOKMARK));
		
		// The last '@' sign is treated specially, so if the 
		// bookmark name contains an '@', then add an extra one to the end
		if (bookmark.getName().indexOf('@') >= 0) {
			action.setText(bookmark.getName() + '@');
		} else {
			action.setText(bookmark.getName());
		}
		ActionContributionItem item = new ActionContributionItem(action);
		item.fill(menu, -1);
	}
}