/* 
-*- coding: latin-1 -*-

This file is part of RefactorErl.

RefactorErl is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

RefactorErl 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with RefactorErl.  If not, see <http://plc.inf.elte.hu/erlang/>.

The Original Code is RefactorErl.

The Initial Developer of the Original Code is Eötvös Loránd University.
Portions created  by Eötvös Loránd University and ELTE-Soft Ltd.
are Copyright 2007-2025 Eötvös Loránd University, ELTE-Soft Ltd.
and Ericsson Hungary. All Rights Reserved.
*/

package com.refactorerl.ui.presentation.investigations;

import java.util.List;

import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.AbstractFormPart;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.widgets.ColumnLayout;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import com.refactorerl.ui.communication.exceptions.CommunicationException;
import com.refactorerl.ui.communication.exceptions.ConnectionException;
import com.refactorerl.ui.communication.exceptions.RequestException;
import com.refactorerl.ui.logic.investigations.Investigation;
import com.refactorerl.ui.logic.investigations.InvestigationNode;
import com.refactorerl.ui.presentation.Activator;
import com.refactorerl.ui.presentation.queries.QueryDialog;


/**
 * Implements the details side of the InvestigationMasterDetailsBlock. This always displays
 * data about the selected node on the master side.
 * @author Daniel Lukacs, 2014 ELTE IK
 *
 */
public class InvestigationDetailsPage extends AbstractFormPart implements IDetailsPage {

	private Label nameLabel;
	private Text nameText;
	private Button showButton;
	private Text textText;
	private FormToolkit toolkit;
	private Composite nodeDetails;
	private Composite upperComposite;
	private Composite lowerComposite;
	private Section section;
	private InvestigationMasterDetailsBlock master;
	final private InvestigationEditor editor;
	private InvestigationNode selectedNode = null;
	private Button memoButton;
	private Button newInvNodeButton;
	private Button deleteButton;
	private Button newInvSubtreeButton;
	private Label showLabel;

	public InvestigationDetailsPage(FormToolkit toolkit, InvestigationEditor editor,
			InvestigationMasterDetailsBlock master) {
		this.toolkit = toolkit;
		this.editor = editor;
		this.master = master;
	}

	@Override
	public void createContents(Composite parent) {

		parent.setLayout(new ColumnLayout());
		section = toolkit.createSection(parent, Section.DESCRIPTION | Section.TITLE_BAR);
		section.setText(Messages.InvestigationDetailsPage_0);
		section.setDescription(Messages.InvestigationDetailsPage_1);

		nodeDetails = toolkit.createComposite(section);
		nodeDetails.setLayout(new RowLayout(SWT.VERTICAL));
		createUpperComposite(nodeDetails);
		createLowerComposite(nodeDetails);

		section.setClient(nodeDetails);
	}

	/**
	 * Creates the composite holding the buttons to manipulate the currently
	 * selected investigation node.
	 * 
	 * @param nodeDetails
	 */
	private void createLowerComposite(final Composite nodeDetails) {
		lowerComposite = toolkit.createComposite(nodeDetails);
		final GridLayout layout2 = new GridLayout();
		lowerComposite.setLayout(layout2);

		layout2.numColumns = 2;

		memoButton = toolkit.createButton(lowerComposite, Messages.InvestigationDetailsPage_2, SWT.PUSH);
		GridData gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		memoButton.setLayoutData(gd);

		newInvNodeButton = toolkit.createButton(lowerComposite, Messages.InvestigationDetailsPage_3, SWT.PUSH);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		newInvNodeButton.setLayoutData(gd);

		deleteButton = toolkit.createButton(lowerComposite, Messages.InvestigationDetailsPage_4, SWT.PUSH);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		deleteButton.setLayoutData(gd);

		newInvSubtreeButton = toolkit.createButton(lowerComposite, Messages.InvestigationDetailsPage_5, SWT.PUSH);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		newInvSubtreeButton.setLayoutData(gd);

		memoButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {

				InputDialog dialog = new InputDialog(nodeDetails.getShell(), Messages.InvestigationDetailsPage_6,
						Messages.InvestigationDetailsPage_7, "", //$NON-NLS-3$
						null);
				if (dialog.open() == InputDialog.OK) {
					master.getInput()
							.addMemo(Activator.getProxy().generatePid(), selectedNode, dialog.getValue(), null);
					master.refresh();
					editor.inputChanged();
				}
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// not called

			}
		});
		deleteButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				master.getInput().removeNode(selectedNode);
				master.refresh();
				editor.inputChanged();

			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// not called

			}
		});
		newInvNodeButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				InputDialog dialog = new InputDialog(nodeDetails.getShell(), Messages.InvestigationDetailsPage_9,
						Messages.InvestigationDetailsPage_10, "", null); //$NON-NLS-2$
				if (dialog.open() == InputDialog.OK && !dialog.getValue().trim().isEmpty()) {

					Investigation inv = Investigation.createInvestigationWithNode(dialog.getValue().trim(), Activator
							.getProxy().getNodeName(), selectedNode);
					try {
						InvestigationHelper.showNewInvestigation(inv, PlatformUI.getWorkbench()
								.getActiveWorkbenchWindow().getActivePage());
					} catch (PartInitException | RequestException | ConnectionException | CommunicationException e1) {
						Activator.showErrorDialog(e1, nodeDetails.getShell());
					}

				}
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// not called

			}
		});

		newInvSubtreeButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				InputDialog dialog = new InputDialog(nodeDetails.getShell(), Messages.InvestigationDetailsPage_12,
						Messages.InvestigationDetailsPage_13, "", null); //$NON-NLS-2$
				if (dialog.open() == InputDialog.OK && !dialog.getValue().trim().isEmpty()) {

					Investigation inv = Investigation.createInvestigationWithSubtree(dialog.getValue().trim(),
							Activator.getProxy().getNodeName(), selectedNode);
					try {
						InvestigationHelper.showNewInvestigation(inv, PlatformUI.getWorkbench()
								.getActiveWorkbenchWindow().getActivePage());
					} catch (PartInitException | RequestException | ConnectionException | CommunicationException e1) {
						Activator.showErrorDialog(e1, nodeDetails.getShell());
					}

				}
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// not called

			}
		});

	}

	/**
	 * Creates the composite hosting the fields which are containing information
	 * about the selected investigation node.
	 * 
	 * @param nodeDetails
	 */
	private void createUpperComposite(final Composite nodeDetails) {
		upperComposite = toolkit.createComposite(nodeDetails);
		upperComposite.setLayout(new GridLayout(2, false));

		nameLabel = toolkit.createLabel(upperComposite, Messages.InvestigationDetailsPage_15);
		configureGridData(nameLabel, false);

		nameText = toolkit.createText(upperComposite, "", SWT.BORDER //$NON-NLS-1$
				| SWT.BORDER_DASH);
		configureGridData(nameText, true);

		showLabel = toolkit.createLabel(upperComposite, Messages.InvestigationDetailsPage_17);
		configureGridData(showLabel, false);

		showButton = toolkit.createButton(upperComposite, "", SWT.CHECK); //$NON-NLS-1$
		configureGridData(showButton, true);

		textText = toolkit.createText(upperComposite, "", SWT.BORDER //$NON-NLS-1$
				| SWT.MULTI | SWT.WRAP);

		GridData gd = configureGridData(textText, false);
		gd.horizontalSpan = 2;

		textText.setEditable(false);

		// when a memo is selected
		textText.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {

				// textText.pack();
				section.layout();
				section.pack();
			}
		});

		nameText.addModifyListener(new DirtyModifyListener() {

			@Override
			protected void doModifyText(ModifyEvent e) {
				selectedNode.name = nameText.getText();
			}
		});
		textText.addModifyListener(new DirtyModifyListener() {

			@Override
			protected void doModifyText(ModifyEvent e) {
				selectedNode.text = textText.getText();

			}
		});

		textText.addMouseListener(new MouseListener() {

			@Override
			public void mouseUp(MouseEvent e) {
				if (selectedNode.memo)
					return;

				QueryDialog d = new QueryDialog(nodeDetails.getShell(), Messages.InvestigationDetailsPage_20,
						Messages.InvestigationDetailsPage_21 + Messages.InvestigationDetailsPage_22
								+ Messages.InvestigationDetailsPage_23);
				if (d.open() == QueryDialog.OK) {
					String query = d.getValue();
					List<InvestigationNode> selection = InvestigationHelper.showSelectResultNodeDialog(query,
							selectedNode, textText.getCaretPosition(), PlatformUI.getWorkbench()
									.getActiveWorkbenchWindow().getActivePage());
					if (selection == null)
						return;
					for (InvestigationNode invNode : selection) {
						master.getInput().addNode(invNode);
					}

					master.refresh();
					editor.inputChanged();

				}
				nodeDetails.setFocus();

			}

			@Override
			public void mouseDown(MouseEvent e) {
			}

			@Override
			public void mouseDoubleClick(MouseEvent e) {
			}
		});

		showButton.addSelectionListener(new DirtySelectionListener());
	}

	abstract class DirtyModifyListener implements ModifyListener {

		@Override
		public void modifyText(ModifyEvent e) {
			// markDirty();

			Text t = (Text) e.getSource();
			if (t.isFocusControl()) {
				doModifyText(e);
				editor.inputChanged();
			}
		}

		abstract protected void doModifyText(ModifyEvent e);
	}

	class DirtySelectionListener implements SelectionListener {

		@Override
		public void widgetSelected(SelectionEvent e) {
			// markDirty();

			selectedNode.shown = ((Button) e.getSource()).getSelection();

			editor.inputChanged();
		}

		@Override
		public void widgetDefaultSelected(SelectionEvent e) {
		}

	}

	@Override
	public void selectionChanged(IFormPart part, ISelection selection) {

		selectedNode = (InvestigationNode) ((ITreeSelection) selection).getFirstElement();

		section.setText(selectedNode.memo ? Messages.InvestigationDetailsPage_24 : Messages.InvestigationDetailsPage_25);
		section.setDescription(selectedNode.memo ? Messages.InvestigationDetailsPage_26
				+ Messages.InvestigationDetailsPage_27 : Messages.InvestigationDetailsPage_28
				+ Messages.InvestigationDetailsPage_29);

		textText.setEditable(selectedNode.memo);
		nameText.setText(selectedNode.name);
		showButton.setSelection(selectedNode.shown);
		textText.setText(selectedNode.text);
		GridData gd = (GridData) textText.getLayoutData();
		gd.grabExcessHorizontalSpace = false;
		gd.widthHint = lowerComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;

		// textText.pack();

		configureVisible(nameText, !selectedNode.memo);
		configureVisible(nameLabel, !selectedNode.memo);
		configureVisible(showButton, !selectedNode.memo);
		configureVisible(showLabel, !selectedNode.memo);

		section.layout();
		section.pack();

	}

	private GridData configureGridData(Control ctrl, boolean rowEnd) {
		GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, rowEnd, false);
		gd.exclude = false;
		ctrl.setLayoutData(gd);
		return gd;
	}

	private void configureVisible(Control ctrl, boolean visible) {
		ctrl.setVisible(visible);
		GridData gd = (GridData) ctrl.getLayoutData();
		gd.exclude = !visible;
	}

}