/*
 *  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 org.apache.commons.lang3.StringUtils;
import org.dbgl.exception.InvalidMountstringException;
import org.dbgl.gui.GeneralPurposeDialogs;
import org.dbgl.gui.abstractdialog.SizeControlledButtonDialog;
import org.dbgl.gui.controls.BrowseButton;
import org.dbgl.gui.controls.BrowseButton.BrowseType;
import org.dbgl.gui.controls.BrowseButton.CanonicalType;
import org.dbgl.model.conf.mount.DirMount;
import org.dbgl.model.conf.mount.ImageMount;
import org.dbgl.model.conf.mount.Mount;
import org.dbgl.model.conf.mount.PhysFsMount;
import org.dbgl.model.factory.MountFactory;
import org.dbgl.util.StringRelatedUtils;
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.Combo;
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 EditMountDialog extends SizeControlledButtonDialog<String> {

	private final String mount_;
	private final char driveletter_;

	public EditMountDialog(Shell parent, String mount, char driveletter) {
		super(parent, "mountdialog");
		mount_ = mount;
		driveletter_ = driveletter;
	}

	@Override
	protected String getDialogTitle() {
		return (mount_ == null) ? text_.get("dialog.mount.title.add"): text_.get("dialog.mount.title.edit");
	}

	@Override
	protected void onShellCreated() {
		contents_.setLayout(new GridLayout(5, false));

		Combo driveletter = createLabelAndCombo(contents_, text_.get("dialog.mount.driveletter"), false, 4, "ABCDEFGHIJKLMNOPQRSTUVWXY".split("(?!^)"), 10);
		Button mountDirButton = createRadioButton(contents_, text_.get("dialog.mount.mountdir"));
		Text dirMountDir = createText(contents_, 3);
		new BrowseButton(contents_).connect(shell_, dirMountDir, null, BrowseType.DIR, CanonicalType.DOSROOT, false, null);
		createLabel(contents_, 1, 4);
		Combo dirMountType = createLabelAndCombo(contents_, text_.get("dialog.mount.mountdiras"), false, 3, settings_.getValues("profile", "mount_type"), 10);
		dirMountType.add(StringUtils.EMPTY, 0);
		Text dirMountLabel = createLabelAndText(contents_, text_.get("dialog.mount.drivelabel"), 3);
		Composite lowlevelComposite = createInnerComposite(contents_, new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1), 4);
		Combo dirMountLowlevelCdType = createLabelAndCombo(lowlevelComposite, text_.get("dialog.mount.lowlevelcdsupport"), settings_.getValues("profile", "lowlevelcd_type"), 10);
		dirMountLowlevelCdType.add(StringUtils.EMPTY, 0);
		Combo dirMountUseCd = createLabelAndCombo(lowlevelComposite, text_.get("dialog.mount.usecd"), new String[] {StringUtils.EMPTY, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}, 10);
		Combo dirMountFreesize = createLabelAndEditableCombo(contents_, text_.get("dialog.mount.freesize"), settings_.getValues("profile", "freesize"), 10);
		dirMountFreesize.add(StringUtils.EMPTY, 0);
		Label dirMountMbLabel = createLabel(contents_, 2, 1);

		createHorizontalSeparator(contents_, 5);

		Button mountImageButton = createRadioButton(contents_, text_.get("dialog.mount.mountimages"));
		Text imgMountImage = createTextarea(contents_, false, false, 3, 1, null);
		BrowseButton imgBrowseButton = new BrowseButton(contents_);
		createLabel(contents_, 1, 2);
		createLabel(contents_, text_.get("dialog.mount.mountdiras"));
		Composite imgComposite = createInnerComposite(contents_, new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1), 3);
		Combo imgMountType = createCombo(imgComposite, settings_.getValues("profile", "imgmount_type"), 10);
		imgMountType.setText("iso");
		Combo imgMountFs = createLabelAndCombo(imgComposite, text_.get("dialog.mount.imgmountfs"), settings_.getValues("profile", "imgmount_fs"), 10);
		imgMountFs.add(StringUtils.EMPTY, 0);
		Text imgMountSize = createLabelAndText(contents_, text_.get("dialog.mount.imgmountsize"), 2);
		Button imgSizeHelperButton = createThreeDotButton(contents_, new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				String command = new EditImgSizeDialog(shell_, imgMountSize.getText()).open();
				if (command != null)
					imgMountSize.setText(command);
			}
		});
		imgBrowseButton.connect(shell_, imgMountImage, null, BrowseType.FILE, CanonicalType.CDIMAGE, false, imgMountType);

		createHorizontalSeparator(contents_, 5);

		Button mountZipButton = createRadioButton(contents_, text_.get("dialog.mount.mountzip"));
		Text zipMountZip = createLabelAndText(contents_, text_.get("dialog.mount.zipfile"), 2);
		new BrowseButton(contents_).connect(shell_, zipMountZip, null, BrowseType.FILE, CanonicalType.ZIP, false, null);
		createLabel(contents_, 1, 3);
		Text zipMountWrite = createLabelAndText(contents_, text_.get("dialog.mount.writedirectory"), 2);
		new BrowseButton(contents_).connect(shell_, zipMountWrite, null, BrowseType.DIR, CanonicalType.DOSROOT, false, null);
		Combo zipMountType = createLabelAndCombo(contents_, text_.get("dialog.mount.mountzipas"), false, 3, settings_.getValues("profile", "zipmount_type"), 10);
		zipMountType.add(StringUtils.EMPTY, 0);
		Text zipMountLabel = createLabelAndText(contents_, text_.get("dialog.mount.drivelabel"), 3);

		dirMountType.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				updateInterfaceElements(imgSizeHelperButton, dirMountUseCd, dirMountFreesize, dirMountMbLabel, dirMountType, dirMountLowlevelCdType, imgMountFs, imgMountSize);
			}
		});

		imgMountFs.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				updateInterfaceElements(imgSizeHelperButton, dirMountUseCd, dirMountFreesize, dirMountMbLabel, dirMountType, dirMountLowlevelCdType, imgMountFs, imgMountSize);
			}
		});

		SelectionAdapter driveLetterSelectionAdapter = new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				boolean imgFsNone = "none".equalsIgnoreCase(imgMountFs.getText());
				int sel = driveletter.getSelectionIndex();
				if (mountImageButton.getSelection() && imgFsNone) {
					if (!StringUtils.isNumeric(driveletter.getItem(sel))) {
						driveletter.setItems(new String[] {"0", "1", "2", "3"});
						driveletter.setText(driveletter.getItem(Math.min(sel, 3)));
					}
				} else {
					if (StringUtils.isNumeric(driveletter.getItem(sel))) {
						driveletter.setItems("ABCDEFGHIJKLMNOPQRSTUVWXY".split("(?!^)"));
						driveletter.setText(driveletter.getItem(Math.min(sel, 3)));
					}
				}
			}
		};

		imgMountFs.addSelectionListener(driveLetterSelectionAdapter);
		mountDirButton.addSelectionListener(driveLetterSelectionAdapter);
		mountImageButton.addSelectionListener(driveLetterSelectionAdapter);
		mountZipButton.addSelectionListener(driveLetterSelectionAdapter);

		createOkCancelButtons(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				if (!isValid(mountDirButton, dirMountDir, mountImageButton, imgMountImage, imgMountFs, imgMountSize, mountZipButton, zipMountZip)) {
					return;
				}
				Mount mount = null;
				if (mountDirButton.getSelection()) {
					mount = MountFactory.createDirMount(driveletter.getText(), dirMountDir.getText(), dirMountType.getText(), dirMountLabel.getText(),
						dirMountLowlevelCdType.isEnabled() ? dirMountLowlevelCdType.getText(): null, dirMountFreesize.isEnabled() ? dirMountFreesize.getText(): null,
						dirMountUseCd.isEnabled() ? dirMountUseCd.getText(): null);
				} else if (mountImageButton.getSelection()) {
					mount = MountFactory.createImageMount(driveletter.getText(), StringRelatedUtils.textAreaToStringArray(imgMountImage.getText(), imgMountImage.getLineDelimiter()),
						imgMountType.getText(), imgMountFs.getText(), imgMountSize.isEnabled() ? imgMountSize.getText(): null);
				} else if (mountZipButton.getSelection()) {
					mount = MountFactory.createPhysFsMount(driveletter.getText(), zipMountZip.getText(), zipMountWrite.getText(), zipMountType.getText(), zipMountLabel.getText());
				}
				if (mount != null) {
					result_ = mount.toString();
				}
				shell_.close();
			}
		});

		ModifyListener modListener = new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				mountDirButton.setSelection(event.widget == dirMountDir);
				mountImageButton.setSelection(event.widget == imgMountImage);
				mountZipButton.setSelection(event.widget == zipMountZip);
				mountDirButton.notifyListeners(SWT.Selection, null);
			}
		};

		dirMountDir.addModifyListener(modListener);
		imgMountImage.addModifyListener(modListener);
		zipMountZip.addModifyListener(modListener);

		Mount mount = null;
		if (mount_ != null) {
			try {
				mount = MountFactory.create(mount_);
			} catch (InvalidMountstringException e1) {
				// if the mount could not be instantiated, use default values
			}
		}
		if (mount == null)
			mount = MountFactory.createDefaultNewMount(driveletter_);

		driveletter.select(mount.getDrive() - 'A');
		if (mount instanceof PhysFsMount) {
			PhysFsMount physFsMount = (PhysFsMount)mount;
			mountZipButton.setSelection(true);
			zipMountZip.setText(physFsMount.getPath().getPath());
			if (physFsMount.getWrite() != null)
				zipMountWrite.setText(physFsMount.getWrite().getPath());
			if (StringUtils.isNotBlank(physFsMount.getMountAs())) {
				zipMountType.setText(physFsMount.getMountAs());
			}
			zipMountLabel.setText(physFsMount.getLabel());
			zipMountZip.selectAll();
			zipMountZip.setFocus();
		} else if (mount instanceof ImageMount) {
			ImageMount imageMount = (ImageMount)mount;
			mountImageButton.setSelection(true);
			if (StringUtils.isNotBlank(imageMount.getMountAs())) {
				imgMountType.setText(imageMount.getMountAs());
			}
			if (imageMount.getFs().equalsIgnoreCase("none")) {
				driveletter.setItems(new String[] {"0", "1", "2", "3"});
			}
			if (StringUtils.isNotBlank(imageMount.getFs())) {
				imgMountFs.setText(imageMount.getFs());
			}
			if (StringUtils.isNotBlank(imageMount.getSize())) {
				imgMountSize.setText(imageMount.getSize());
			}
			imgMountImage.setText(StringRelatedUtils.stringArrayToString(imageMount.getImgPathStrings(), imgMountImage.getLineDelimiter()));
			imgMountImage.selectAll();
			imgMountImage.setFocus();
		} else if (mount instanceof DirMount) {
			DirMount dirMount = (DirMount)mount;
			mountDirButton.setSelection(true);
			dirMountDir.setText(dirMount.getPath().getPath());
			if (StringUtils.isNotBlank(dirMount.getMountAs())) {
				dirMountType.setText(dirMount.getMountAs());
			}
			dirMountLabel.setText(dirMount.getLabel());
			dirMountLowlevelCdType.setText(dirMount.getLowlevelCD());
			dirMountUseCd.setText(dirMount.getUseCD());
			if (StringUtils.isNotBlank(dirMount.getFreesize())) {
				dirMountFreesize.setText(dirMount.getFreesize());
			}
			dirMountDir.selectAll();
			dirMountDir.setFocus();
		}
		driveletter.setText(mount.getDriveAsString());

		updateInterfaceElements(imgSizeHelperButton, dirMountUseCd, dirMountFreesize, dirMountMbLabel, dirMountType, dirMountLowlevelCdType, imgMountFs, imgMountSize);
	}

	private void updateInterfaceElements(Button img_size_config, Combo usecd, Combo freesize, Label mbLabel, Combo mount_type, Combo lowlevelcd_type, Combo imgmount_fs, Text imgmount_size) {
		boolean enableLLItems = "cdrom".equalsIgnoreCase(mount_type.getText());
		lowlevelcd_type.setEnabled(enableLLItems);
		usecd.setEnabled(enableLLItems);
		freesize.setEnabled(!enableLLItems);

		String sizeLabel = "floppy".equalsIgnoreCase(mount_type.getText()) ? text_.get("dialog.mount.kb"): text_.get("dialog.mount.mb");
		mbLabel.setText(sizeLabel);
		mbLabel.pack();

		boolean imgFsNone = "none".equalsIgnoreCase(imgmount_fs.getText());
		imgmount_size.setEnabled(imgFsNone);
		img_size_config.setEnabled(imgFsNone);
	}

	private boolean isValid(Button imgSizeHelperButton, Text dirMountDir, Button mountImageButton, Text imgMountImage, Combo imgMountFs, Text imgMountSize, Button mountZipButton, Text zipMountZip) {
		GeneralPurposeDialogs.initErrorDialog();
		if (imgSizeHelperButton.getSelection() && StringUtils.isBlank(dirMountDir.getText())) {
			GeneralPurposeDialogs.addError(text_.get("dialog.mount.required.path"), dirMountDir);
		} else if (mountImageButton.getSelection()) {
			if (StringUtils.isBlank(imgMountImage.getText()))
				GeneralPurposeDialogs.addError(text_.get("dialog.mount.required.image"), imgMountImage);
			if (imgMountFs.getText().equalsIgnoreCase("none") && StringUtils.isBlank(imgMountSize.getText()))
				GeneralPurposeDialogs.addError(text_.get("dialog.mount.required.imgsize"), imgMountSize);
		} else if (mountZipButton.getSelection() && StringUtils.isBlank(zipMountZip.getText())) {
			GeneralPurposeDialogs.addError(text_.get("dialog.mount.required.zip"), zipMountZip);
		}
		return !GeneralPurposeDialogs.displayErrorDialog(shell_);
	}
}
