/**
 * Copyright (C) 2019 Patrik Dufresne Service Logiciel <info@patrikdufresne.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package com.planimod.ui;

import static com.planimod.ui.Localized._;

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.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";
    /**
     * Preference key to define the number of files to keep in preferences.
     */
    protected static final String PREFKEY_MAX_RECENT_FILES = "DatabaseSelectorDialog.max_recent.files";
    /**
     * Resource id for title image.
     */
    private static final String TITLE_IMAGE = "DatabaseSelectorDialog.titleImage";

    /**
     * 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 String 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();
            }
        }
    };

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

    /**
     * This implementation set the windows title
     */
    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText(_("Selectionnez une base de données"));
    }

    @Override
    protected Control createContents(Composite parent) {
        Control control = super.createContents(parent);
        // sets title area message
        setDatabaseURL(null);
        setTitle(_("Selectionnez une base de données"));
        setMessage(_("Ce logiciel enregistre les données dans une base de données locale."));
        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(_("Base de données :"));

        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"));
        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 String getManagersConfig() {
        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) {
            this.dbUrl = url;
            setErrorMessage(null);
        } else {
            this.dbUrl = null;
        }

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

}
