/*
 *  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.function.BiConsumer;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils;
import org.dbgl.gui.GeneralPurposeDialogs;
import org.dbgl.gui.abstractdialog.EditConfigurableDialog;
import org.dbgl.gui.controls.MetaControl;
import org.dbgl.model.aggregate.DosboxVersion;
import org.dbgl.model.aggregate.Template;
import org.dbgl.model.entity.TemplateProfileBase;
import org.dbgl.model.factory.TemplateFactory;
import org.dbgl.model.repository.DosboxVersionRepository;
import org.dbgl.model.repository.TemplateRepository;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;


public class EditTemplateDialog extends EditConfigurableDialog<Template> {

	private final static boolean multiEdit = false;

	private Text title_;

	private Template template_;
	private final boolean editing_;

	public EditTemplateDialog(Shell parent, Template template) {
		super(parent, "templatedialog");
		template_ = template;
		editing_ = template_ != null;
	}

	@Override
	protected String getDialogTitle() {
		return editing_ ? text_.get("dialog.template.title.edit", new Object[] {template_.getTitle(), template_.getId()}): text_.get("dialog.template.title.add");
	}

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

		try {
			if (editing_) {
				dbversionIndex_ = DosboxVersionRepository.indexOf(dbversionsList_, template_.getDosboxVersion());
			} else {
				template_ = TemplateFactory.create(DosboxVersionRepository.findDefault(dbversionsList_));
			}
			String warningsLog = template_.resetAndLoadConfiguration();
			if (StringUtils.isNotBlank(warningsLog))
				GeneralPurposeDialogs.warningMessage(getParent(), warningsLog);
			return true;
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(getParent(), e);
			return false;
		}
	}

	private void updateControlsByTemplate() {
		metaControls_.forEach(x -> x.setControlByTemplate(template_, multiEdit));

		updateControlsByConfigurable(template_, multiEdit);
	}

	private void updateTemplateByControls() {
		metaControls_.forEach(x -> x.updateTemplateByControl(template_));

		updateConfigurableByControls(template_);
	}

	protected void doPerformDosboxConfAction(DosboxConfAction action, DosboxVersion newDosboxVersion) {
		try {
			updateConfigurableByControls(template_);

			StringBuffer warningsLog = new StringBuffer(newDosboxVersion.resetAndLoadConfiguration());

			if (action == DosboxConfAction.SET)
				warningsLog.append(template_.setToDosboxVersion(newDosboxVersion));
			else if (action == DosboxConfAction.SWITCH)
				warningsLog.append(template_.switchToDosboxVersion(newDosboxVersion));
			else if (action == DosboxConfAction.RELOAD)
				warningsLog.append(template_.reloadDosboxVersion(newDosboxVersion));

			updateControlsByConfigurable(template_, multiEdit);

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

	@Override
	protected void onShellCreated() {
		createInfoTab();
		createGeneralTab(text_.get("dialog.profile.automatic"), editing_ ? template_.getConfigurationCanonicalFile().getPath(): SettingsDialog.confFilenames[0]);
		createDisplayTab();
		createMachineTab();
		createAudioTab();
		createIOTab();
		createCustomCommandsTab(template_, multiEdit);
		createMountingTab(template_, multiEdit);
		createOkCancelButtons();

		updateControlsByTemplate();

		if (!editing_)
			title_.setFocus();
	}

	protected void createInfoTab() {
		Composite composite = createTabWithComposite(text_.get("dialog.template.tab.info"), 2);

		title_ = createLabelAndTextMetaControl(composite, text_.get("dialog.template.title"), Template::getTitle, Template::setTitle);
		createLabelAndCheckboxMetaControl(composite, text_.get("dialog.template.default"), Template::getDefault, Template::setDefault);
	}

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

		Composite booterComposite = (Composite)booterExpandItem_.getControl();
		booterComposite.setLayout(new GridLayout());
		createLabel(booterComposite, text_.get("dialog.profile.booterimage1"));

		Composite dosComposite = (Composite)dosExpandItem_.getControl();
		dosComposite.setLayout(new GridLayout());
		createLabel(dosComposite, text_.get("dialog.profile.mainexe"));
	}

	protected void createOkCancelButtons() {
		createOkCancelButtons(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				if (!isValid()) {
					return;
				}
				try {
					updateTemplateByControls();

					if (editing_) {
						new TemplateRepository().update(template_);
						result_ = template_;
					} else {
						result_ = new TemplateRepository().add(template_);
					}
				} catch (Exception e) {
					GeneralPurposeDialogs.warningMessage(shell_, e);
				}
				shell_.close();
			}
		});
	}

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

	private Text createLabelAndTextMetaControl(Composite composite, String labelText, Function<Template, String> getMethod, BiConsumer<Template, String> updateMethod) {
		Label label = createLabel(composite, labelText);
		Text text = createText(composite);
		metaControls_.add(new MetaControl(label, text).connectTemplate(getMethod, updateMethod));
		return text;
	}

	private Button createLabelAndCheckboxMetaControl(Composite composite, String labeltext, Function<Template, String> getMethod, BiConsumer<Template, String> updateMethod) {
		Label label = createLabel(composite, labeltext);
		Button checkButton = createCheckButton(composite, false);
		metaControls_.add(new MetaControl(label, checkButton).connectTemplate(getMethod, updateMethod));
		return checkButton;
	}
}
