/*
 * Copyright (c) 2013, Patrik Dufresne. All rights reserved.
 * Patrik Dufresne PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.planimod.ui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

import com.patrikdufresne.jface.preference.PreferenceConverter;
import com.patrikdufresne.jface.resource.OverlayImageDescriptor;
import com.patrikdufresne.managers.DatabaseUrl;
import com.patrikdufresne.util.Localized;
import com.planimod.ui.preference.PlanimodPreferences;
import com.planimod.ui.theme.Resources;

/**
 * This dialog is used to allow the user to select a database.
 * 
 * @author Patrik Dufresne
 * 
 */
public class DatabaseSelectorDialog extends TitleAreaDialog {

	/**
	 * Default value.
	 */
	protected static final int PREF_MAX_RECENT_FILES_DEFAULT = 5;
	/**
	 * Preference key to access the files list.
	 */
	protected static final String PREFKEY_FILES_LIST = "DatabaseSelectorDialog.files"; //$NON-NLS-1$
	/**
	 * Preference key to define the number of files to keep in preferences.
	 */
	protected static final String PREFKEY_MAX_RECENT_FILES = "DatabaseSelectorDialog.max_recent.files"; //$NON-NLS-1$
	/**
	 * Resource id for title image.
	 */
	private static final String TITLE_IMAGE = "DatabaseSelectorDialog.titleImage"; //$NON-NLS-1$

	/**
	 * Return the title image
	 * 
	 * @return
	 */
	private static Image getTitleImage() {
		Image image = JFaceResources.getImage(TITLE_IMAGE);
		if (image == null) {
			OverlayImageDescriptor icon = new OverlayImageDescriptor(
					JFaceResources.getImageRegistry().getDescriptor(
							DLG_IMG_TITLE_BANNER),
					Resources.getImageDescriptor(Resources.APP_ICON_48),
					SWT.LEFT, SWT.CENTER);
			JFaceResources.getImageRegistry().put(TITLE_IMAGE, icon);
			image = JFaceResources.getImage(TITLE_IMAGE);
		}
		return image;
	}

	/**
	 * The browse button
	 */
	protected Button browseButton;

	private Combo combo;

	/**
	 * The current database url.
	 */
	private DatabaseUrl dbUrl;

	/**
	 * Listen to browser button selection.
	 */
	private Listener listener = new Listener() {
		@Override
		public void handleEvent(Event event) {
			if (event.widget == DatabaseSelectorDialog.this.browseButton) {
				handleBrowse();
			} else {
				handleModify();
			}
		}
	};

	/**
	 * Localized string
	 */
	private Localized localized = Localized.load(DatabaseSelectorDialog.class);

	/**
	 * Create a new dialog to select the database to open.
	 * 
	 * @param parentShell
	 */
	public DatabaseSelectorDialog(Shell parentShell) {
		super(parentShell);
	}

	@Override
	protected void cancelPressed() {
		this.dbUrl = null;
		super.cancelPressed();
	}

	/**
	 * This implementation set the windows title
	 */
	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText(localized.get("DatabaseSelectorDialog.title")); //$NON-NLS-1$
	}

	@Override
	protected Control createContents(Composite parent) {
		Control control = super.createContents(parent);
		// sets title area message
		setDatabaseURL(null);
		setTitle(localized.get("DatabaseSelectorDialog.titleArea.title")); //$NON-NLS-1$
		setMessage(localized.get("DatabaseSelectorDialog.titleArea.message")); //$NON-NLS-1$
		setTitleImage(getTitleImage());

		// Create viewer values
		String[] files = PreferenceConverter.getStringArray(
				PlanimodPreferences.getPreferenceStore(), PREFKEY_FILES_LIST);
		for (int i = 0; i < files.length; i++) {
			this.combo.add(files[i]);
		}
		if (files.length > 0)
			this.combo.setText(files[files.length - 1]);

		return control;
	}

	/**
	 * This implementation create the controsl to selecte a database file.
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite composite = (Composite) super.createDialogArea(parent);

		// Create widgets
		Composite comp = new Composite(composite, SWT.NONE);
		comp.setLayout(new GridLayout(3, false));
		comp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));

		Label label = new Label(comp, SWT.NONE);
		label.setText(this.localized
				.get("DatabaseSelectorDialog.databaseLabel")); //$NON-NLS-1$

		this.combo = new Combo(comp, SWT.BORDER);
		this.combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		this.combo.addListener(SWT.Modify, this.listener);

		this.browseButton = new Button(comp, SWT.PUSH);
		this.browseButton.setText(JFaceResources.getString("openBrowse")); //$NON-NLS-1$
		this.browseButton.addListener(SWT.Selection, this.listener);

		// Build the separator line
		Label separator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
		separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		return composite;
	}

	/**
	 * Return the selected database url or null.
	 * 
	 * @return
	 */
	public DatabaseUrl getDatabaseUrl() {
		return this.dbUrl;
	}

	/**
	 * Notify this class about the user selecting the browse button.
	 */
	void handleBrowse() {
		FileDialog dlg = new FileDialog(getShell(), SWT.OPEN);
		String fileSelected = dlg.open();
		if (fileSelected != null) {
			this.combo.setText(fileSelected);
		}
	}

	/**
	 * Notify this class when the combo box is modify.
	 */
	void handleModify() {
		String url = this.combo.getText();
		setDatabaseURL(url);
	}

	@Override
	protected void okPressed() {
		// Set default and get value of the maximum number a file in the recent
		// list
		IPreferenceStore preferenceStore = PlanimodPreferences
				.getPreferenceStore();
		preferenceStore.setDefault(PREFKEY_MAX_RECENT_FILES,
				PREF_MAX_RECENT_FILES_DEFAULT);
		int maxNumberOfFile = preferenceStore.getInt(PREFKEY_MAX_RECENT_FILES);

		// Get previous recent list from preferences
		List<String> list = Arrays.asList(PreferenceConverter.getStringArray(
				preferenceStore, PREFKEY_FILES_LIST));
		list = new ArrayList<String>(list);

		// Add current selection to the recent list
		String currentSelection = this.combo.getText();
		if (list.contains(currentSelection)) {
			list.remove(currentSelection);
		}
		list.add(currentSelection);
		// Reduce the size of the list
		while (list.size() > maxNumberOfFile)
			list.remove(0);

		// Save recent file list in preferences
		String[] array = new String[list.size()];
		list.toArray(array);
		PreferenceConverter.setValue(preferenceStore, PREFKEY_FILES_LIST, array);

		super.okPressed();
	}

	/**
	 * Sets the database url.
	 * 
	 * @param url
	 */
	protected void setDatabaseURL(String url) {

		if (url != null) {
			try {
				this.dbUrl = new DatabaseUrl(url);
				if (this.dbUrl.isLocal()) {
					this.dbUrl.test();
				}
				setErrorMessage(null);
			} catch (IOException e) {
				setErrorMessage(e.getLocalizedMessage());
			}
		} else {
			this.dbUrl = null;
		}

		this.getButton(IDialogConstants.OK_ID).setEnabled(this.dbUrl != null);
	}

}
