/*
 *  Copyright (C) 2006-2019  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.dialog;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.dbgl.gui.GeneralPurposeDialogs;
import org.dbgl.gui.abstractdialog.EditProfileDialog;
import org.dbgl.gui.dialog.wizard.UpdateMultiProfileDialog;
import org.dbgl.model.aggregate.DosboxVersion;
import org.dbgl.model.aggregate.Profile;
import org.dbgl.model.aggregate.Template;
import org.dbgl.model.entity.TemplateProfileBase;
import org.dbgl.model.factory.ProfileFactory;
import org.dbgl.model.repository.DosboxVersionRepository;
import org.dbgl.util.searchengine.WebSearchEngine;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;


public class EditMultiProfileDialog extends EditProfileDialog<List<Profile>> {

	private final static boolean multiEdit = true;

	private List<Profile> profiles_, orgProfiles_;
	private Profile profile_;
	private boolean dbversionChanged_, templateReloaded_;

	public EditMultiProfileDialog(Shell parent, List<Profile> profiles) {
		super(parent);
		profiles_ = profiles;
		orgProfiles_ = profiles_.stream().map(x -> ProfileFactory.createCopy(x)).collect(Collectors.toList());
	}

	@Override
	protected String getDialogTitle() {
		return text_.get("dialog.multiprofile.title.edit", new Object[] {profiles_.size()});
	}

	@Override
	protected boolean prepare() {
		if (!super.prepare())
			return false;

		try {
			StringBuffer warningsLog = new StringBuffer();

			profile_ = ProfileFactory.combine(dbversionsList_, profiles_, warningsLog);
			dbversionIndex_ = DosboxVersionRepository.indexOf(dbversionsList_, profile_.getDosboxVersion());
			templateIndex_ = -1;

			if (StringUtils.isNotEmpty(warningsLog)) {
				GeneralPurposeDialogs.warningMessage(getParent(), warningsLog.toString());
			}
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	protected void doPerformDosboxConfAction(DosboxConfAction action, DosboxVersion newDosboxVersion) {
		try {
			StringBuffer warningsLog = new StringBuffer();

			for (Profile prof: profiles_) {
				metaControls_.stream().filter(x -> x.hasChangedValue()).forEach(x -> x.updateProfileByControl(prof));
				daControls_.stream().filter(x -> x.hasChangedValue()).forEach(x -> x.updateConfigurationByControl(prof));
				autoexecControls_.stream().filter(x -> x.hasChangedValue()).forEach(x -> x.updateAutoexecByControl(prof.getConfiguration().getAutoexec()));

				warningsLog.append(newDosboxVersion.resetAndLoadConfiguration());

				if (action == DosboxConfAction.SET) {
					warningsLog.append(prof.setToDosboxVersion(newDosboxVersion));
					dbversionChanged_ = true;
				} else if (action == DosboxConfAction.SWITCH) {
					warningsLog.append(prof.switchToDosboxVersion(newDosboxVersion));
					dbversionChanged_ = true;
				} else if (action == DosboxConfAction.RELOAD) {
					warningsLog.append(prof.reloadDosboxVersion(newDosboxVersion));
					dbversionChanged_ = true;
				} else if (action == DosboxConfAction.RELOAD_TEMPLATE) {
					Template templ = templatesList_.get(templateCombo_.getSelectionIndex());
					warningsLog.append(templ.resetAndLoadConfiguration());
					warningsLog.append(prof.reloadTemplate(newDosboxVersion, templ));
					templateReloaded_ = true;
				}
			}

			profile_ = ProfileFactory.combine(dbversionsList_, profiles_, warningsLog);

			updateControlsByConfigurable(profile_, multiEdit);

			if (StringUtils.isNotEmpty(warningsLog)) {
				GeneralPurposeDialogs.warningMessage(getParent(), warningsLog.toString());
			}
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(getParent(), e);
		}
	}

	private void updateControlsByProfile() {
		metaControls_.forEach(x -> x.setControlByProfile(profile_, multiEdit));

		updateControlsByConfigurable(profile_, multiEdit);
	}

	@Override
	protected void updateControlsByConfigurable(TemplateProfileBase configurable, boolean multiEdit) {
		super.updateControlsByConfigurable(configurable, multiEdit);

		loadfixValue_.setEnabled(loadfix_.getSelection());
	}

	@Override
	protected void onShellCreated() {
		createInfoTab();
		createGeneralTab(text_.get("dialog.profile.automatic"),
			SettingsDialog.confLocations[settings_.getIntValue("profiledefaults", "confpath")] + ", " + SettingsDialog.confFilenames[settings_.getIntValue("profiledefaults", "conffile")]);
		createDisplayTab();
		createMachineTab();
		createAudioTab();
		createIOTab();
		createCustomCommandsTab(profile_, multiEdit);
		createMountingTab(profile_, multiEdit);
		createOkCancelButtons();

		updateControlsByProfile();

		Stream.of(daControls_, metaControls_, autoexecControls_).flatMap(Collection::stream).forEach(x -> x.addListeners());
	}

	@Override
	protected ToolBar createInfoTab() {
		ToolBar toolBar = super.createInfoTab();
		engineSelector_.addToggleSelectionListener(false);
		return toolBar;
	}

	protected void createOkCancelButtons() {
		createOkCancelButtons(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				if (!isValid()) {
					return;
				}
				try {
					UpdateMultiProfileDialog empDialog = new UpdateMultiProfileDialog(shell_, orgProfiles_, profiles_, dbversionChanged_, templateReloaded_, daControls_, autoexecControls_,
							metaControls_, engineSelector_.isSelected() ? WebSearchEngine.getBySimpleName(settings_.getValue("gui", "searchengine")): null);

					if (empDialog.open() != null) {
						result_ = profiles_;
						shell_.close();
					}
				} catch (Exception e) {
					GeneralPurposeDialogs.warningMessage(shell_, e);
				}
			}
		});
	}

	protected boolean isValid() {
		GeneralPurposeDialogs.initErrorDialog();
		if (setButton_.isEnabled()) {
			GeneralPurposeDialogs.addError(text_.get("dialog.template.required.dosboxassociation"), setButton_, getTabItemByControl(setButton_));
		}
		return !GeneralPurposeDialogs.displayErrorDialog(shell_);
	}
}
