/*
 *  Copyright (C) 2006-2012  Ronald Blankendaal
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
package org.dbgl.gui;

import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.apache.commons.lang3.StringUtils;
import org.dbgl.db.Database;
import org.dbgl.model.Filter;
import org.dbgl.model.Profile;
import org.dbgl.model.conf.Settings;
import swing2swt.layout.BorderLayout;


public final class EditFilterDialog extends Dialog {

    private Text filter;
    private Text title;
    private String prevTitle;
    private Set<Integer> selectedProfileIds;
    private Database dbase;
    private Object result;
    private Shell shell;
    private Settings settings;


    public EditFilterDialog(final Shell parent) {
        super(parent, SWT.NONE);
    }

    public void setFilter(final Filter filter) {
        this.result = filter;
    }

	public void setIds(Set<Integer> selectedProfileIds) {
		this.selectedProfileIds = selectedProfileIds;
	}

    public Object open() {
        dbase = Database.getInstance();
        settings = Settings.getInstance();
        createContents();
        shell.open();
        shell.layout();
        Display display = getParent().getDisplay();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        return result;
    }

    private void createContents() {
        shell = new Shell(getParent(), SWT.TITLE | SWT.CLOSE | SWT.BORDER | SWT.RESIZE | SWT.APPLICATION_MODAL);
        shell.setLayout(new BorderLayout(0, 0));
        shell.addControlListener(new SizeControlAdapter(shell, "filterdialog"));

        if (result == null) {
            shell.setText(settings.msg("dialog.filter.title.add"));
        } else {
            // meaning we are essentially editing an existing filter
            shell.setText(settings.msg("dialog.filter.title.edit", 
                    new Object[] {((Filter) result).getTitle(), ((Filter) result).getId()}));
        }

        final TabFolder tabFolder = new TabFolder(shell, SWT.NONE);

        TabItem infoTabItem = new TabItem(tabFolder, SWT.NONE);
        infoTabItem.setText(settings.msg("dialog.filter.tab.info"));

        final Composite composite = new Composite(tabFolder, SWT.NONE);
        final GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        composite.setLayout(gridLayout);
        infoTabItem.setControl(composite);

        final Label titleLabel = new Label(composite, SWT.NONE);
        titleLabel.setText(settings.msg("dialog.filter.title"));

        title = new Text(composite, SWT.BORDER);
        title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        final Label filterLabel = new Label(composite, SWT.NONE);
        filterLabel.setText(settings.msg("dialog.filter.filter"));

        filter = new Text(composite, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL);
        filter.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        final Label resultLabel = new Label(composite, SWT.NONE);
        resultLabel.setText(settings.msg("dialog.filter.result"));
        
        final Text results = new Text(composite, SWT.BORDER | SWT.READ_ONLY);
        results.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        final Composite composite_7 = new Composite(shell, SWT.NONE);
        composite_7.setLayout(new GridLayout(2, true));
        composite_7.setLayoutData(BorderLayout.SOUTH);

        final Button okButton = new Button(composite_7, SWT.NONE);
        shell.setDefaultButton(okButton);
        final GridData gridData = new GridData();
        gridData.horizontalAlignment = SWT.FILL;
        gridData.widthHint = 80;
        okButton.setLayoutData(gridData);
        okButton.setText(settings.msg("button.ok"));
        okButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
                if (!isValid()) {
                    return;
                }
                try {
                    int filterId = dbase.addOrEditFilter(title.getText(), filter.getText(), result == null ? -1: ((Filter) result).getId());
                    result = new Filter(filterId, title.getText(), filter.getText());
                } catch (SQLException e) {
                    GeneralPurposeDialogs.warningMessage(shell, e);
                }
                shell.close();
            }
        });

        final Button cancelButton = new Button(composite_7, SWT.NONE);
        final GridData gridData_1 = new GridData();
        gridData_1.horizontalAlignment = SWT.FILL;
        cancelButton.setLayoutData(gridData_1);
        cancelButton.setText(settings.msg("button.cancel"));
        cancelButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
                result = null;
                shell.close();
            }
        });
        
        title.addModifyListener(new ModifyListener() {
        	public void modifyText(ModifyEvent arg0) {
        		if (filter.getText().equals("") || filter.getText().equals("UPPER(GAM.TITLE) LIKE '%" + prevTitle.toUpperCase() + "%'")) {
                	if (title.getText().length() == 0) {
                		filter.setText("");
                	} else {
                		filter.setText("UPPER(GAM.TITLE) LIKE '%" + title.getText().toUpperCase() + "%'");
                	}
                }
        		prevTitle = title.getText();
        	}
        });
        filter.addModifyListener(new ModifyListener() {
        	public void modifyText(ModifyEvent arg0) {
        		try {
                    List<Profile> tmpList = dbase.readProfilesList("", filter.getText());
                    results.setText(settings.msg("dialog.filter.notice.results", new Object[] {tmpList.size()}));
                    okButton.setEnabled(true);
                } catch (SQLException e) {
                    results.setText(settings.msg("dialog.filter.error.invalidcondition"));
                    okButton.setEnabled(false);
                }
        	}
        });

        // init values
        if (result != null) {
            // meaning we are essentially editing an existing filter
            // so we need to set previous values
            title.setText(((Filter) result).getTitle());
            filter.setText(((Filter) result).getFilter());
        } else {
        	prevTitle = "";
        	if (selectedProfileIds != null) {
        		filter.setText("GAM.ID IN (" + StringUtils.join(selectedProfileIds, ',') + ")");
        	}
        }
        title.setFocus();
    }

    private boolean isValid() {
        GeneralPurposeDialogs.initErrorDialog();
        if (title.getText().equals("")) {
            GeneralPurposeDialogs.addError(settings.msg("dialog.filter.required.title"), title);
        }
        return !GeneralPurposeDialogs.displayErrorDialog(shell);
    }
}
