/*
 *  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;

/*
 * 0. title, choose A) install game, B) pre-installed game
 * 
 * Install:
 * 1 choose install.exe, add mount c data\tmpinst to mounts, start installer, end with exit
 * 2 ask for patch, if available have the user copy the files into data\tmpinst and run exe
 * 
 * Pre-installed:
 * 3 choose main+setup for just installed game using combo
 * 4 choose main+setup for pre-installed game using browse
 * 5 suggest moving game into dosroot, have the user choose the exact location
 * 6 choose template, machine, core, cycles, mounts
 */

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.dbgl.db.Database;
import org.dbgl.gui.BrowseButton.BrowseType;
import org.dbgl.gui.BrowseButton.CanonicalType;
import org.dbgl.model.DosboxVersion;
import org.dbgl.model.ExpProfile;
import org.dbgl.model.KeyValuePair;
import org.dbgl.model.Mount;
import org.dbgl.model.Profile;
import org.dbgl.model.Template;
import org.dbgl.model.WebProfile;
import org.dbgl.model.conf.Conf;
import org.dbgl.model.conf.SectionsWrapper;
import org.dbgl.model.conf.Settings;
import org.dbgl.swtdesigner.SWTImageManager;
import org.dbgl.util.FileUtils;
import org.dbgl.util.StringRelatedUtils;
import org.dbgl.util.searchengine.HotudSearchEngine;
import org.dbgl.util.searchengine.MobyGamesSearchEngine;
import org.dbgl.util.searchengine.PouetSearchEngine;
import org.dbgl.util.searchengine.WebSearchEngine;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;


public class AddGameWizardDialog extends Wizard {

	final static java.util.List<WebSearchEngine> webSearchEngines = Arrays.asList(MobyGamesSearchEngine.getInstance(), PouetSearchEngine.getInstance(), HotudSearchEngine.getInstance());
	
	private static final String[] CUST_STRINGS = new String[] { "", "", "", "", "", "", "", "" };
	
	private Text title;
	private String developer, publisher, year, genre, notes;
	private String[] link = new String[] { "", "", "", "", "", "", "", "" };
    private String[] linkTitle = new String[] { "", "", "", "", "", "", "", "" };
    private final int[] customInts = new int[] { 0, 0 };
	
	private Button doSearch, moveImages, templateReload;
	private ToolItem engineSelector;
	private Button btnPreinstalledGame, btnGameNeedsToBeInstalled, btnInstallManual, btnPatchManual;
	private Combo main, setup;
	private Text mainText, setupText;
	private Text installExe, installParameters, patchExe, patchParameters, dstDirectory, imagesDstDirectory;
	private List mountingpoints;
	private File[] installedFiles, orgImages;
	private List installedFilesList, orgImagesList;
	private Combo template;
	private Combo machine, core, cycles;
	
	private Database dbase;
	private java.util.List<DosboxVersion> dbversionsList;
	private java.util.List<Template> templatesList;
	private ExpProfile profile;
	private int templateIndex = -1;
	

    public AddGameWizardDialog(final Shell parent, final int style) {
        super(parent, style, Settings.getInstance().msg("dialog.addgamewizard.title"), "addgamewizard", false);
    }

    protected boolean init() {
    	dbase = Database.getInstance();
    	
    	try {
            dbversionsList = dbase.readDosboxVersionsList();
            templatesList = dbase.readTemplatesList();
            
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(bos);
            
            DosboxVersion dbversion = DosboxVersion.findDefault(dbversionsList);
        	templateIndex = Template.indexOfDefault(templatesList);
        	if (templateIndex != -1) {
        		profile = new ExpProfile(new Conf((File)null, templatesList.get(templateIndex), dbversion, ps));
        	} else {
        		profile = new ExpProfile(new Conf((File)null, (Template)null, dbversion, ps));
        	}
        	
        	developer = "";
        	publisher = "";
        	year = "";
        	genre = "";
        	notes = "";
        	
            return true;
        } catch (Exception e) {
            GeneralPurposeDialogs.warningMessage(getParent(), e);
            return false;
        }
    }
    
	protected void onExit() {
		try {
			org.apache.commons.io.FileUtils.deleteDirectory(FileUtils.getTmpInstallFile());
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(shell, e);
		}
	}
    
    protected int stepSize(boolean up) {
    	if (btnPreinstalledGame.getSelection()) {
    		if ((up && stepNr == 0) || (!up && stepNr == 4))
    			return 4; // skip installing and patching and maincombo
    		if ((up && stepNr == 4) || (!up && stepNr == 6)) // FileUtils.belowDosRoot(profile.getConf().getAutoexec().getCanonicalMainDir())
    			return 2; // skip moving game data
    	} else {
    		if ((up && stepNr == 3) || (!up && stepNr == 5))
    			return 2; // skip maintext
    	}
		return super.stepSize(up);
	}
    
    protected boolean isValidInput() {
    	GeneralPurposeDialogs.initErrorDialog();
    	if (stepNr == 0) {
    		return titleEntered();
		} else if (stepNr == 1) {
    		return installExeEntered();
		} else if (stepNr == 2) {
    		return true;
		} else if (stepNr == 3) {
    		return mainExeEntered();
		} else if (stepNr == 4) {
    		return mainExeEntered();
		} else if (stepNr == 5) {
    		return conditionsOkForStep5();
		}  else if (stepNr == 6) {
    		return true;
		}
    	return true;
    }
    
    protected boolean actionAfterNext() {
    	if (stepNr == 0) {
    		return doWebSearch();
		} else if (stepNr == 1) {
    		return runInstallerAndCheckResults();
		} else if (stepNr == 2) {
			return determineMainAndSetup();
		} else if (stepNr == 3) {
    		return setMain();
		} else if (stepNr == 4) {
    		return setMain(); //todo maintext
		} else if (stepNr == 5) {
    		return true;
		} else if (stepNr == 6) {
    		return createProfile();
		}
    	return false;
    }

    protected void doReloadTemplate(int templateIndex) {
		try {
	    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	        PrintStream ps = new PrintStream(bos);
	        
	        Conf templateConf = new Conf(templatesList.get(templateIndex), DosboxVersion.findDefault(dbversionsList), ps);
	        profile.getConf().reloadTemplate(templateConf);
        	
		    selectSettingsByConfiguration(profile.getConf());
        
            if (bos.size() > 0) {
            	GeneralPurposeDialogs.warningMessage(getParent(), bos.toString());
            	bos.reset();
            }
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(getParent(), e);
		}
	}
    
    protected void selectSettingsByConfiguration(Conf conf) {
    	SectionsWrapper sections = conf.getSettings();
	    machine.setText(sections.getValue("dosbox", "machine"));
	    core.setText(sections.getValue("cpu", "core"));
	    cycles.setText(sections.getValue("cpu", "cycles"));
    }
    
    protected void updateConfigurationBySettings(Conf conf) {
        conf.updateValue("dosbox", "machine", machine.getText(), true);
        conf.updateValue("cpu", "core", core.getText(), true);
        conf.updateValue("cpu", "cycles", cycles.getText(), true);
	}
    
    protected void doAddMount() {
        final EditMountDialog addMountDialog = new EditMountDialog(shell);
        try {
            addMountDialog.setDefaultDriveletter(Mount.getFreeDriveletter(false, profile.getConf().nettoMountedDriveLetters()));
        } catch (Exception e) {
            // nothing we can do, just take default 'C'
        }
        String mount = (String) addMountDialog.open();
        if (mount != null) {
            mountingpoints.setItems(profile.getConf().addMount(mount));
            mountingpoints.select(mountingpoints.getItemCount() - 1);
        }
    }

    protected void doEditMount() {
        int mounts = mountingpoints.getItemCount();
        int sel = mountingpoints.getSelectionIndex();
        if (sel != -1) {
            final EditMountDialog editMountDialog = new EditMountDialog(shell);
            editMountDialog.setMount(mountingpoints.getItem(sel));
            String mount = (String) editMountDialog.open();
            if (mount != null) {
                mountingpoints.setItems(profile.getConf().editMount(sel, mount));
                if (mountingpoints.getItemCount() == mounts) {
                    mountingpoints.select(sel);
                } else {
                    mountingpoints.select(mountingpoints.getItemCount() - 1);
                }
            }
        }
    }
    
    protected void doRemoveMount() {
        int mounts = mountingpoints.getItemCount();
        int sel = mountingpoints.getSelectionIndex();
        if (sel == -1 && mounts == 1) { sel = 0; mountingpoints.select(sel); }
        if (sel != -1) {
            mountingpoints.setItems(profile.getConf().removeMount(sel));
            if (mountingpoints.getItemCount() == mounts) {
                mountingpoints.select(sel);
            } else {
                if (mountingpoints.getItemCount() > 0) {
                    mountingpoints.select(mountingpoints.getItemCount() - 1);
                }
            }
        }
    }
    
    private boolean titleEntered() {
        if (title.getText().trim().length() <= 0)
        	GeneralPurposeDialogs.addError(settings.msg("dialog.profile.required.title"), title);
        return !GeneralPurposeDialogs.displayErrorDialog(shell);
    }
    
    private boolean doWebSearch() {
    	if (doSearch.getSelection()) {
    		String currTitle = title.getText();
        	if (currTitle.length() >= 1) {
        		WebSearchEngine engine = getSelectedSearchEngine();
        		try {
            		WebProfile thisGame = null;
        			java.util.List<WebProfile> webGamesList = engine.getEntries(currTitle, 
        					settings.getSettings().getValues(engine.getSimpleName(), "platform_filter"));
        			if (webGamesList.size() == 1) {
        				thisGame = webGamesList.get(0);
        			} else if (webGamesList.size() > 1) {
        				BrowseSearchEngineDialog mobyDialog = new BrowseSearchEngineDialog(shell);
        				mobyDialog.setProfilesToBrowse(currTitle, webGamesList);
        				mobyDialog.setEngine(engine);
	        			Integer idx = (Integer)mobyDialog.open();
	        			if (idx != null) {
	        				thisGame = webGamesList.get(idx);
	        			}
        			}
        			if (thisGame != null) {
        				final WebProfile profExt = engine.getEntryDetailedInformation(thisGame);
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_title"))
        					title.setText(profExt.getTitle());
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_developer"))
        					developer = profExt.getDeveloperName();
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_publisher"))
        					publisher = profExt.getPublisherName();
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_year"))
        					year = profExt.getYear();
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_genre"))
        					genre = profExt.getGenre();
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_link")) {
        					link[0] = profExt.getUrl();
        					linkTitle[0] = settings.msg("dialog.profile.searchengine.link.maininfo", new String[] { engine.getName() });
        				}
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_description")) {
        					notes = profExt.getNotes();
        				}
        				if (settings.getSettings().getBooleanValue(engine.getSimpleName(), "set_rank")) {
        					customInts[0] = profExt.getRank();
        				}
        			}
        		} catch (Exception e) {
        			GeneralPurposeDialogs.warningMessage(shell, settings.msg("general.error.retrieveinfosearchengine", new String[] {engine.getName(), currTitle, StringRelatedUtils.toString(e)}), e);
        		}
        	}
    	}
    	
    	if (btnGameNeedsToBeInstalled.getSelection()) {
    		profile.getConf().unmountDosboxMounts();
    		profile.getConf().addMount("mount c \"" + FileUtils.getTmpInstallFile() + "\"");
            mountingpoints.setItems(profile.getConf().getAutoexec().getMountingpoints());
    	}
    	return true;
	}
    
	private boolean installExeEntered() {
        if (installExe.getText().trim().length() <= 0)
        	GeneralPurposeDialogs.addError(settings.msg("dialog.addgamewizard.required.installexe"), installExe);
        return !GeneralPurposeDialogs.displayErrorDialog(shell);
	}
	
	private boolean runInstallerAndCheckResults() {
    	try {
    		org.apache.commons.io.FileUtils.deleteDirectory(FileUtils.getTmpInstallFile());
    		FileUtils.createDir(FileUtils.getTmpInstallFile());
    		
   			profile.getConf().getAutoexec().setMainExecutable(installExe.getText(), installParameters.getText());
    		
			FileUtils.doRunInstaller(profile, profile.getConf(), dbversionsList, null, btnInstallManual.getSelection());
			shell.forceFocus();
			shell.forceActive();
			
			orgImages = profile.getConf().getFirstImageMountPath();
			installedFiles = FileUtils.getTmpInstallFile().listFiles();
			if (installedFiles.length == 0) {
				GeneralPurposeDialogs.warningMessage(shell, settings.msg("dialog.addgamewizard.error.nofilesinstalled"));
				return false;
			}
			
			return true;
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(shell, e);
			return false;
		}
    }
    
    private boolean determineMainAndSetup() {
    	if (patchExe.getText().trim().length() > 0) {
	    	try {
	    		profile.getConf().getAutoexec().setMainExecutable(patchExe.getText(), patchParameters.getText());
	    		
				FileUtils.doRunInstaller(profile, profile.getConf(), dbversionsList, null, btnPatchManual.getSelection());
				shell.forceFocus();
				shell.forceActive();
			} catch (IOException e) {
				GeneralPurposeDialogs.warningMessage(shell, e);
				return false;
			}
    	}    	
    	

    	orgImagesList.removeAll();
    	if (orgImages != null) {
	    	for (File file: orgImages) {
	    		orgImagesList.add(FileUtils.makeRelativeToDosroot(file).getPath());
	        }
    	}
    	orgImagesList.selectAll();
    	orgImagesList.pack();
    	orgImagesList.getParent().layout();
    	
    	installedFilesList.removeAll();
    	File gameDir = null;
		for (File file: installedFiles) {
			if (file.isDirectory()) {
				installedFilesList.add("[ " + FileUtils.makeRelativeToDosroot(file).getPath() + " ]");
				if (gameDir == null) gameDir = file;
			} else {
				installedFilesList.add(FileUtils.makeRelativeToDosroot(file).getPath());
			}
        }
    	installedFilesList.selectAll();
    	installedFilesList.pack();
    	installedFilesList.getParent().layout();
    	
    	moveImages.setEnabled(profile.getConf().countImageMounts() == 1);
    	String imagesDirString = settings.getSettings().getValue("directory", "orgimages");
    	File imagesSubDir = gameDir != null? new File(gameDir.getName(), imagesDirString): new File(imagesDirString);
    	imagesDstDirectory.setText(imagesSubDir.getPath());
    	
    	java.util.List<File> executables = FileUtils.getExecutablesInDirRecursive(FileUtils.getTmpInstallFile());
    	
    	main.removeAll();
    	setup.removeAll();
    	setup.add("");
    	for (File f: executables) {
    		main.add(FileUtils.makeRelativeToDosroot(f).getPath());
    		setup.add(FileUtils.makeRelativeToDosroot(f).getPath());
    	}
        if (executables.isEmpty())
        	main.add(installExe.getText());
        int mainFileIndex = FileUtils.findMostLikelyMainIndex(title.getText(), executables);
    	if (mainFileIndex != -1) {
    		main.select(mainFileIndex);
    	} else {
    		main.select(0);
    	}
    	int setupFileIndex = FileUtils.findSetupIndex(executables);
    	if (setupFileIndex != -1) {
    		setup.select(setupFileIndex + 1);
    	} else {
    		setup.select(0);
    	}
        setup.setEnabled(setup.getItemCount() > 1);
		return true;
    }
    
    private boolean mainExeEntered() {
    	if (btnPreinstalledGame.getSelection()) {
    		if (mainText.getText().trim().length() <= 0)
	        	GeneralPurposeDialogs.addError(settings.msg("dialog.profile.required.mainexe"), mainText);
    	} else {
	    	if (main.getText().trim().length() <= 0)
	        	GeneralPurposeDialogs.addError(settings.msg("dialog.profile.required.mainexe"), main);
    	}
        return !GeneralPurposeDialogs.displayErrorDialog(shell);
    }
    
    private boolean setMain() {
    	if (btnPreinstalledGame.getSelection()) {
    		if (profile.getConf().getRequiredMount(false, mainText.getText()) != null) {
    			profile.getConf().addRequiredMount(false, mainText.getText());
    		}
    		profile.getConf().getAutoexec().setMainExecutable(mainText.getText(), "");
    	} else {
    		if (profile.getConf().getRequiredMount(false, main.getText()) != null) {
    			profile.getConf().addRequiredMount(false, main.getText());
    		}
    		profile.getConf().getAutoexec().setMainExecutable(main.getText(), "");
    	}
    	return true;
    }
    
    private boolean conditionsOkForStep5() {
    	if (btnPreinstalledGame.getSelection()) return true;
		
		try {
			if (installedFilesList.getSelectionCount() > 0) {
				File destDir = new File(dstDirectory.getText());
				if (!destDir.isDirectory()) {
					if (GeneralPurposeDialogs.confirmMessage(shell, settings.msg("dialog.addgamewizard.confirm.createdestinationdir", new String[] {destDir.toString()}))) {
						destDir.mkdirs();
					}
				}
				if (!destDir.isDirectory()) {
					GeneralPurposeDialogs.addError(settings.msg("dialog.addgamewizard.error.destinationdirmissing", new String[] {destDir.toString()}), dstDirectory);
				} else {
					for (int i = 0; i < installedFiles.length; i++) {
						if (installedFilesList.isSelected(i)) {
							File destFile = new File(destDir, installedFiles[i].getName());
							if (org.apache.commons.io.FileUtils.directoryContains(destDir, destFile)) {
								GeneralPurposeDialogs.addError(settings.msg("dialog.addgamewizard.error.gamedatadirexists", new String[] {destFile.toString()}), dstDirectory);
							}
						}
					}
				}
			} else {
				GeneralPurposeDialogs.addError(settings.msg("dialog.addgamewizard.error.gamedatamustbemoved"), installedFilesList);
			}
			
			return !GeneralPurposeDialogs.displayErrorDialog(shell);
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(shell, e);
			return false;
		}
	}

	private boolean createProfile() {
		try {
			
			String setupString = btnPreinstalledGame.getSelection()? setupText.getText(): setup.getText();
			
			if (installedFilesList.getSelectionCount() > 0) {
				File destDir = new File(dstDirectory.getText());
				profile.getConf().getAutoexec().migrateTo(FileUtils.getTmpInstallFile(), destDir);
				profile.getConf().removeFloppyMounts();
				profile.getConf().removeUnnecessaryMounts();

				if (StringUtils.isNotBlank(setupString)) {
					setupString = FileUtils.makeRelativeTo(FileUtils.canonicalToDosroot(setupString), FileUtils.getTmpInstallFile()).getPath();
					setupString = FileUtils.makeRelativeToDosroot(new File(destDir, setupString)).getPath();
				}
				
				for (int i = 0; i < installedFiles.length; i++) {
					File src = installedFiles[i];
					if (installedFilesList.isSelected(i)) {
						org.apache.commons.io.FileUtils.moveToDirectory(src, destDir, true);
					}
				}
				
				if (moveImages.getSelection()) {
					File imgDestDir = new File(destDir, imagesDstDirectory.getText());
					FileUtils.createDir(imgDestDir);
					
					for (int i = 0; i < orgImages.length; i++) {
						File src = orgImages[i];
						if (orgImagesList.isSelected(i)) {
							org.apache.commons.io.FileUtils.moveToDirectory(src, imgDestDir, true);
						}
					}
				}
			}
			
			String status = "";
	        boolean favorite = false;
			int devId = KeyValuePair.findIdByValue(dbase.readDevelopersList(), developer);
	        int publId = KeyValuePair.findIdByValue(dbase.readPublishersList(), publisher);
	        int genId = KeyValuePair.findIdByValue(dbase.readGenresList(), genre);
	        int yrId = KeyValuePair.findIdByValue(dbase.readYearsList(), year);
	        int statId = KeyValuePair.findIdByValue(dbase.readStatusList(), status);
	        
	        int[] custIDs = new int[] { 0, 0, 0, 0 };
	        for (int i = 0; i < 4; i++) {
	            custIDs[i] = KeyValuePair.findIdByValue(dbase.readCustomList(i), "");
	    	}
	        
			dbase.startTransaction();
			
			int profileId = dbase.addOrEditProfile(title.getText(), developer, publisher, genre, year, status, notes, favorite, 
	        		new String[] { setupString, "", "" }, new String[] { "", "", "" },
	                devId, publId, genId, yrId, statId, profile.getDbversionId(),
	                link, linkTitle, CUST_STRINGS, customInts, custIDs, -1);
			
			String confString = FileUtils.constructUniqueConfigFileString(profileId, title.getText(), profile.getConf().getAutoexec().getCanonicalMainDir());
			String capturesString = FileUtils.constructCapturesDir(profileId);
			FileUtils.createDir(FileUtils.canonicalToData(capturesString));
			dbase.updateProfileConf(confString, capturesString, profileId);
			
			Profile p = new Profile(profileId, title.getText(), developer, publisher, genre, year, status, notes, favorite,
					new String[] { setupString, "", "" }, new String[] { "", "", "" },
            		confString, capturesString, profile.getDbversionId(), 
            		link, linkTitle, CUST_STRINGS, customInts);
            
			updateConfigurationBySettings(profile.getConf());
            profile.getConf().injectOrUpdateProfile(p);
            profile.getConf().save();

            dbase.commitTransaction();
            
            result = p;
			
		} catch (IOException e) {
            GeneralPurposeDialogs.warningMessage(shell, e);
            try {
				dbase.rollbackTransaction();
			} catch (SQLException se) {
				GeneralPurposeDialogs.warningMessage(shell, se);
			}
        } catch (SQLException e) {
        	GeneralPurposeDialogs.warningMessage(shell, e);
            try {
				dbase.rollbackTransaction();
			} catch (SQLException se) {
				GeneralPurposeDialogs.warningMessage(shell, se);
			}
		} finally {
        	dbase.finishTransaction();
        }
		
		return true;
	}
	
    private WebSearchEngine getSearchEngineBySimpleName(String simpleName) {
    	for (WebSearchEngine engn: webSearchEngines) {
    		if (engn.getSimpleName().equalsIgnoreCase(simpleName))
    			return engn;
        }
    	return null;
    }
    
    private WebSearchEngine getSelectedSearchEngine() {
		WebSearchEngine engine = null;
		for (WebSearchEngine engn: webSearchEngines) {
			if (engn.getName().equals(doSearch.getData()))
				engine = engn;
		}
		return engine;
	}

    protected void fillPages() {
		addStep(page0());
        addStep(page1());
        addStep(page2());
		addStep(page3());
		addStep(page4());
	    addStep(page5());
	    addStep(page6());
	}

    private Control page0() {
    	final Group group = new Group(shell, SWT.NONE);
        group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        group.setText(settings.msg("dialog.addgamewizard.step1"));
        group.setLayout(new GridLayout(4, false));
        
        final Label titleLabel = new Label(group, SWT.NONE);
        titleLabel.setText(settings.msg("dialog.profile.title"));
        title = new Text(group, SWT.BORDER);
        title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        title.setFocus();

        WebSearchEngine defaultEngine = getSearchEngineBySimpleName(settings.getSettings().getValue("gui", "searchengine"));
        if (defaultEngine == null) defaultEngine = webSearchEngines.get(0);

        doSearch = new Button(group, SWT.TOGGLE);
        doSearch.setText(settings.msg("dialog.profile.consultsearchengine", new String[] { defaultEngine.getName() }));
        doSearch.setData(defaultEngine.getName());
        doSearch.setSelection(settings.getSettings().getBooleanValue("addgamewizard", "consultsearchengine"));
        doSearch.addSelectionListener(new SelectionAdapter() {
        	public void widgetSelected(final SelectionEvent event) {
                settings.getSettings().setBooleanValue("addgamewizard", "consultsearchengine", doSearch.getSelection());
            }
		});

        final ToolBar toolBar = new ToolBar(group, SWT.NONE);
        engineSelector = new ToolItem(toolBar, SWT.DROP_DOWN);
        engineSelector.setImage(SWTImageManager.getResourceImage(shell.getDisplay(), defaultEngine.getIcon()));

        final Menu menu = new Menu(shell, SWT.POP_UP);
        for (final WebSearchEngine engine: webSearchEngines) {
        	MenuItem item = new MenuItem(menu, SWT.PUSH);
        	item.setImage(SWTImageManager.getResourceImage(shell.getDisplay(), engine.getIcon()));
            item.setText(engine.getName());
            item.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(final SelectionEvent event) {
                	MenuItem sel = (MenuItem)event.widget;
                    engineSelector.setImage(sel.getImage());
                    doSearch.setData(sel.getText());
                    doSearch.setText(settings.msg("dialog.profile.consultsearchengine", new String[] { doSearch.getData().toString() }));
                    doSearch.getParent().layout();
                    settings.getSettings().setValue("gui", "searchengine", engine.getSimpleName());
                }
            });
        }

        engineSelector.addListener(SWT.Selection, new Listener() {
          public void handleEvent(Event event) {
            if (event.detail == SWT.ARROW) {
              Rectangle rect = engineSelector.getBounds();
              Point pt = new Point(rect.x, rect.y + rect.height);
              pt = toolBar.toDisplay(pt);
              menu.setLocation(pt.x, pt.y);
              menu.setVisible(true);
            } else {
            	for (int i = 0; i < webSearchEngines.size(); i++) {
            		if (webSearchEngines.get(i).getName().equals(doSearch.getData())) {
            			int nextIdx = i + 1;
            			if (nextIdx >= webSearchEngines.size()) nextIdx = 0;
            			MenuItem sel = menu.getItem(nextIdx);
            			engineSelector.setImage(sel.getImage());
                        doSearch.setData(sel.getText());
                        doSearch.setText(settings.msg("dialog.profile.consultsearchengine", new String[] { doSearch.getData().toString() }));
                        doSearch.getParent().layout();
                        settings.getSettings().setValue("gui", "searchengine", getSelectedSearchEngine().getSimpleName());
                        break;
            		}
            	}
            }
          }
        });
        
        Composite composite = new Composite(group, SWT.NONE);
        composite.setLayout(new GridLayout());
        GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
        gd.verticalIndent = 20;
        composite.setLayoutData(gd);
        final Label thisGameLabel = new Label(composite, SWT.NONE);
        thisGameLabel.setText(settings.msg("dialog.addgamewizard.thisgame"));
        btnPreinstalledGame = new Button(composite, SWT.RADIO);
		btnPreinstalledGame.setText(settings.msg("dialog.addgamewizard.preinstalled"));
		btnGameNeedsToBeInstalled = new Button(composite, SWT.RADIO);
		btnGameNeedsToBeInstalled.setText(settings.msg("dialog.addgamewizard.notyetinstalled"));
		boolean requiresInstallation = settings.getSettings().getBooleanValue("addgamewizard", "requiresinstallation");
		btnPreinstalledGame.setSelection(!requiresInstallation);
		btnGameNeedsToBeInstalled.setSelection(requiresInstallation);
		SelectionAdapter adapter = new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
            	settings.getSettings().setBooleanValue("addgamewizard", "requiresinstallation", event.widget == btnGameNeedsToBeInstalled);
            }
        };
        btnPreinstalledGame.addSelectionListener(adapter);
		btnGameNeedsToBeInstalled.addSelectionListener(adapter);
		
        return group;
    }
    
    private Control page1() {
    	final Group group = new Group(shell, SWT.NONE);
    	group.setText(settings.msg("dialog.addgamewizard.step2"));
    	group.setLayout(new GridLayout());
    	
    	Composite installexeComposite = new Composite(group, SWT.NONE);
    	installexeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    	installexeComposite.setLayout(new GridLayout(3, false));
		final Label mainExeLabel = new Label(installexeComposite, SWT.NONE);
        mainExeLabel.setText(settings.msg("dialog.addgamewizard.installexe"));
        installExe = new Text(installexeComposite, SWT.BORDER);
        installExe.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        final BrowseButton installexeBrowseButton = new BrowseButton(installexeComposite, SWT.NONE);
        installexeBrowseButton.connect(shell, installExe, null, BrowseType.FILE, CanonicalType.INSTALLER, false, null);
        
        final Label parametersLabel = new Label(installexeComposite, SWT.NONE);
        parametersLabel.setText(settings.msg("dialog.profile.mainparameters"));
        installParameters = new Text(installexeComposite, SWT.BORDER);
        installParameters.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
        
        final Label manualLabel = new Label(installexeComposite, SWT.NONE);
        manualLabel.setText(settings.msg("dialog.addgamewizard.manualmode"));
        btnInstallManual = new Button(installexeComposite, SWT.CHECK);
        btnInstallManual.setText(settings.msg("dialog.addgamewizard.manualmodeinfo"));
        btnInstallManual.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
        
        final Group mountGroup = new Group(group, SWT.NONE);
        GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gd.verticalIndent = 20;
        mountGroup.setLayoutData(gd);
        mountGroup.setText(settings.msg("dialog.template.mountingoverview"));
        final GridLayout gridLayout_19 = new GridLayout();
        gridLayout_19.numColumns = 2;
        mountGroup.setLayout(gridLayout_19);

        mountingpoints = new List(mountGroup, SWT.V_SCROLL | SWT.BORDER);
        mountingpoints.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 3));
        mountingpoints.addMouseListener(new MouseAdapter() {
            public void mouseDoubleClick(final MouseEvent event) {
                if (mountingpoints.getSelectionIndex() == -1) {
                    doAddMount();
                } else {
                    doEditMount();
                }
            }
        });

        final Button addButton = new Button(mountGroup, SWT.NONE);
        addButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        addButton.setText(settings.msg("dialog.template.mount.add"));
        addButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
                doAddMount();
            }
        });

        final Button editButton = new Button(mountGroup, SWT.NONE);
        editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        editButton.setText(settings.msg("dialog.template.mount.edit"));
        editButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
                doEditMount();
            }
        });

        final Button removeButton = new Button(mountGroup, SWT.NONE);
        removeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        removeButton.setText(settings.msg("dialog.template.mount.remove"));
        removeButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
                doRemoveMount();
            }
        });
        
        VerifyListener addMountListener = new VerifyListener() {
            public void verifyText(final VerifyEvent event) {
                if (event.text.length() > 1) {
                    addMountIfNoMounts(event.text);
                }
            }
        };
        installExe.addVerifyListener(addMountListener);
        
        return group;
    }
    
    private void addMountIfNoMounts(final String hostFileLocation) {
    	profile.getConf().unmountDosboxMounts();
		profile.getConf().addMount("mount c \"" + FileUtils.getTmpInstallFile() + "\"");
        mountingpoints.setItems(profile.getConf().addRequiredMountForInstaller(hostFileLocation));
    }
    
    private Control page2() {
    	final Group group = new Group(shell, SWT.NONE);
    	group.setText(settings.msg("dialog.addgamewizard.step3")); // patch
    	group.setLayout(new GridLayout());
    	
    	Composite patchexeComposite = new Composite(group, SWT.NONE);
    	patchexeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    	patchexeComposite.setLayout(new GridLayout(3, false));
		final Label patchExeLabel = new Label(patchexeComposite, SWT.NONE);
		patchExeLabel.setText(settings.msg("dialog.addgamewizard.patcherexe"));
		patchExe = new Text(patchexeComposite, SWT.BORDER);
		patchExe.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        final BrowseButton patchexeBrowseButton = new BrowseButton(patchexeComposite, SWT.NONE);
        patchexeBrowseButton.connect(shell, patchExe, null, BrowseType.FILE, CanonicalType.INSTALLER, false, null);
        
        final Label parametersLabel = new Label(patchexeComposite, SWT.NONE);
        parametersLabel.setText(settings.msg("dialog.profile.mainparameters"));
        patchParameters = new Text(patchexeComposite, SWT.BORDER);
        patchParameters.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
        
        final Label manualLabel = new Label(patchexeComposite, SWT.NONE);
        manualLabel.setText(settings.msg("dialog.addgamewizard.manualmode"));
        btnPatchManual = new Button(patchexeComposite, SWT.CHECK);
        btnPatchManual.setText(settings.msg("dialog.addgamewizard.manualpatchmodeinfo"));
        btnPatchManual.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
    	
    	return group;
    }
    
    private Control page3() {
    	final Group group = new Group(shell, SWT.NONE);
    	
    	group.setText(settings.msg("dialog.addgamewizard.step4"));
    	group.setLayout(new GridLayout());
    	
    	Composite composite = new Composite(group, SWT.NONE);
    	composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    	composite.setLayout(new GridLayout(2, false));
		
    	final Label mainExeLabel = new Label(composite, SWT.NONE);
        mainExeLabel.setText(settings.msg("dialog.profile.mainexe"));
        main = new Combo(composite, SWT.READ_ONLY);
        main.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        
        final Label setupExeLabel = new Label(composite, SWT.NONE);
        setupExeLabel.setText(settings.msg("dialog.profile.setupexe"));
        setup = new Combo(composite, SWT.READ_ONLY);
        setup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        
        return group;
    }
    
    private Control page4() {
    	final Group group = new Group(shell, SWT.NONE);
    	
    	group.setText(settings.msg("dialog.addgamewizard.step4"));
    	group.setLayout(new GridLayout());
    	
    	Composite composite = new Composite(group, SWT.NONE);
    	composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    	composite.setLayout(new GridLayout(3, false));
		
    	final Label mainExeLabel = new Label(composite, SWT.NONE);
        mainExeLabel.setText(settings.msg("dialog.profile.mainexe"));
        mainText = new Text(composite, SWT.BORDER);
        mainText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        final BrowseButton mainBrowseButton = new BrowseButton(composite, SWT.NONE);
        mainBrowseButton.connect(shell, mainText, null, BrowseType.FILE, CanonicalType.EXE, false, null);
        
        final Label setupExeLabel = new Label(composite, SWT.NONE);
        setupExeLabel.setText(settings.msg("dialog.profile.setupexe"));
        setupText = new Text(composite, SWT.BORDER);
        setupText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        final BrowseButton setupBrowseButton = new BrowseButton(composite, SWT.NONE);
        setupBrowseButton.connect(shell, setupText, mainText, BrowseType.FILE, CanonicalType.EXE, false, null);
        
        return group;
    }
    
    private Control page5() {
    	final Group group = new Group(shell, SWT.NONE);
    	
    	group.setText(settings.msg("dialog.addgamewizard.step5"));
    	group.setLayout(new GridLayout());
    	
    	final Group installedFilesGroup = new Group(group, SWT.NONE);
    	installedFilesGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
    	installedFilesGroup.setLayout(new GridLayout(3, false));
        installedFilesGroup.setText(settings.msg("dialog.addgamewizard.installedfiles"));

        installedFilesList = new List(installedFilesGroup, SWT.V_SCROLL | SWT.BORDER | SWT.MULTI);
        installedFilesList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
    	
    	final Label toLabel = new Label(installedFilesGroup, SWT.NONE);
		toLabel.setText(settings.msg("dialog.migration.to"));

		dstDirectory = new Text(installedFilesGroup, SWT.BORDER);
		dstDirectory.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		dstDirectory.setText(FileUtils.getDosRoot());
		
		final BrowseButton fromBrowseButton = new BrowseButton(installedFilesGroup, SWT.NONE);
		fromBrowseButton.connect(shell, dstDirectory, null, BrowseType.DIR, CanonicalType.NONE, false, null);
		
		final Group orgImagesGroup = new Group(group, SWT.NONE);
		orgImagesGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		orgImagesGroup.setLayout(new GridLayout(3, false));
		orgImagesGroup.setText(settings.msg("dialog.addgamewizard.originalimages"));
		
		orgImagesList = new List(orgImagesGroup, SWT.V_SCROLL | SWT.BORDER | SWT.MULTI);
		orgImagesList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
		
		final Label moveImagesLabel = new Label(orgImagesGroup, SWT.NONE);
		moveImagesLabel.setText(settings.msg("dialog.addgamewizard.moveimages"));
		moveImages = new Button(orgImagesGroup, SWT.CHECK);
		new Label(orgImagesGroup, SWT.NONE);
		
		final Label imagesToLabel = new Label(orgImagesGroup, SWT.NONE);
		imagesToLabel.setText(settings.msg("dialog.migration.to"));
		imagesDstDirectory = new Text(orgImagesGroup, SWT.BORDER);
		imagesDstDirectory.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		new Label(orgImagesGroup, SWT.NONE);
    	
		moveImages.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
            	imagesDstDirectory.setEnabled(moveImages.getSelection());
            }
        });
		
		imagesDstDirectory.setEnabled(moveImages.getSelection());
		
    	return group;
    }
    
    private Control page6() {
    	final Group group = new Group(shell, SWT.NONE);
    	group.setText(settings.msg("dialog.addgamewizard.step6"));
    	group.setLayout(new GridLayout(3, false));
    	
    	final Label templateLabel = new Label(group, SWT.NONE);
        templateLabel.setText(settings.msg("dialog.profile.template"));
        template = new Combo(group, SWT.READ_ONLY);
        template.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        template.setVisibleItemCount(10);
        for (Template templ : templatesList) {
            template.add(templ.getTitle());
        }
        if (templateIndex != -1) {
            template.select(templateIndex);
        }
        templateReload = new Button(group, SWT.NONE);
        templateReload.setText(settings.msg("dialog.profile.reloadsettings"));
        templateReload.setToolTipText(settings.msg("dialog.profile.reloadsettings.tooltip"));
        templateReload.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(final SelectionEvent event) {
                if (template.getSelectionIndex() != -1) {
                	doReloadTemplate(template.getSelectionIndex());
                }
            }
        });
        
        final Label machineLabel = new Label(group, SWT.NONE);
        machineLabel.setText(settings.msg("dialog.template.machine"));
        machine = new Combo(group, SWT.READ_ONLY);
        machine.setLayoutData(new GridData());
        machine.setVisibleItemCount(20);
        machine.setToolTipText(settings.msg("dialog.template.machine.tooltip"));
        if (profile.getConf().getSettings().detectDosboxVersionGeneration() >= 3) {
        	machine.setItems(settings.getSettings().getValues("profile", "machine073"));
        } else {
        	machine.setItems(settings.getSettings().getValues("profile", "machine"));
        }
        new Label(group, SWT.NONE);
        
        final Label coreLabel = new Label(group, SWT.NONE);
        coreLabel.setText(settings.msg("dialog.template.core"));
        core = new Combo(group, SWT.READ_ONLY);
        core.setLayoutData(new GridData());
        core.setToolTipText(settings.msg("dialog.template.core.tooltip"));
        core.setItems(settings.getSettings().getValues("profile", "core"));
        new Label(group, SWT.NONE);
        
        final Label cyclesLabel = new Label(group, SWT.NONE);
        cyclesLabel.setText(settings.msg("dialog.template.cycles"));
        cycles = new Combo(group, SWT.NONE);
        cycles.setLayoutData(new GridData(100, SWT.DEFAULT));
        cycles.setVisibleItemCount(15);
        cycles.setToolTipText(settings.msg("dialog.template.cycles.tooltip"));
        cycles.setItems(settings.getSettings().getValues("profile", "cycles"));
        new Label(group, SWT.NONE);
        
        selectSettingsByConfiguration(profile.getConf());
        
        return group;
    }
}
