/*
 * Copyright (c) 2013, 2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Christian W. Damus (CEA LIST) - initial API and implementation
 */
package org.eclipse.emf.cdo.security.internal.ui.editor;

import org.eclipse.emf.cdo.security.internal.ui.bundle.OM;
import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
import org.eclipse.emf.cdo.security.internal.ui.util.ObjectExistsConverter.ObjectWritableConverter;
import org.eclipse.emf.cdo.security.internal.ui.util.OneToManyBlock;
import org.eclipse.emf.cdo.security.internal.ui.util.OneToManyTableBlock;
import org.eclipse.emf.cdo.security.provider.SecurityEditPlugin;

import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.databinding.edit.EMFEditObservables;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;

import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IFilter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.SelectionAdapter;
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.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;

/**
 * Common framework for the right-hand side object details pages of the
 * master/detail form.
 *
 * @author Christian W. Damus (CEA LIST)
 */
public abstract class AbstractDetailsPage<T extends EObject> extends AbstractSectionPart<T>implements IDetailsPage
{
  public AbstractDetailsPage(Class<T> elementType, EClass elementEClass, EditingDomain domain,
      AdapterFactory adapterFactory)
  {
    super(elementType, elementEClass, domain, adapterFactory);
  }

  @Override
  protected String getTitle()
  {
    return NLS.bind(Messages.AbstractDetailsPage_0,
        SecurityEditPlugin.INSTANCE.getString(String.format("_UI_%s_type", getInputEClass().getName()))); //$NON-NLS-1$
  }

  @Override
  public void createContents(Composite parent)
  {
    GridLayout layout = new GridLayout();
    parent.setLayout(layout);

    super.createContents(parent);
  }

  @Override
  protected void createContents(Composite parent, FormToolkit toolkit)
  {
    GridLayout layout = new GridLayout();
    layout.numColumns = 2;
    parent.setLayout(layout);
  }

  protected void execute(Command command)
  {
    if (command.canExecute())
    {
      getEditingDomain().getCommandStack().execute(command);
    }
  }

  protected Text text(Composite parent, FormToolkit toolkit, String label, EAttribute attribute)
  {
    toolkit.createLabel(parent, label);
    Text result = toolkit.createText(createDecorationComposite(parent, toolkit, layoutData(parent, SWT.FILL, false, 1)),
        ""); //$NON-NLS-1$
    getContext().bindValue(observeText(result),
        EMFEditObservables.observeDetailValue(getRealm(), getEditingDomain(), getValue(), attribute));
    getContext().bindValue(WidgetProperties.enabled().observe(result), getValue(), null,
        ObjectWritableConverter.createUpdateValueStrategy(attribute));

    addRevertDecoration(result, attribute);
    return result;
  }

  private static GridData horzAlign(GridData gridData, int align, boolean grab, int span)
  {
    gridData.horizontalAlignment = align;
    gridData.grabExcessHorizontalSpace = grab;
    gridData.horizontalSpan = span;
    return gridData;
  }

  private static GridData vertAlign(GridData gridData, int align, boolean grab, int span)
  {
    gridData.verticalAlignment = align;
    gridData.grabExcessVerticalSpace = grab;
    gridData.verticalSpan = span;
    return gridData;
  }

  private static TableWrapData horzAlign(TableWrapData tableData, int align, boolean grab, int span)
  {
    int tableWrapAlign = 0;
    switch (align)
    {
    case SWT.LEFT:
      tableWrapAlign = TableWrapData.LEFT;
      break;
    case SWT.CENTER:
      tableWrapAlign = TableWrapData.CENTER;
      break;
    case SWT.RIGHT:
      tableWrapAlign = TableWrapData.RIGHT;
      break;
    case SWT.FILL:
      tableWrapAlign = TableWrapData.FILL;
      break;
    }

    tableData.align = tableWrapAlign;
    tableData.grabHorizontal = grab;
    tableData.colspan = span;
    return tableData;
  }

  private static TableWrapData vertAlign(TableWrapData tableData, int align, boolean grab, int span)
  {
    int tableWrapAlign = 0;
    switch (align)
    {
    case SWT.TOP:
      tableWrapAlign = TableWrapData.TOP;
      break;
    case SWT.CENTER:
      tableWrapAlign = TableWrapData.MIDDLE;
      break;
    case SWT.BOTTOM:
      tableWrapAlign = TableWrapData.BOTTOM;
      break;
    case SWT.FILL:
      tableWrapAlign = TableWrapData.FILL;
      break;
    }

    tableData.valign = tableWrapAlign;
    tableData.grabVertical = grab;
    tableData.rowspan = span;
    return tableData;
  }

  protected static Object layoutData(Composite parent, int horzAlign, boolean horzGrab, int horzSpan)
  {
    if (parent.getLayout() instanceof GridLayout)
    {
      return horzAlign(new GridData(), horzAlign, horzGrab, horzSpan);
    }

    return horzAlign(new TableWrapData(), horzAlign, horzGrab, horzSpan);
  }

  protected static Object layoutData(Composite parent, int horzAlign, boolean horzGrab, int horzSpan, int vertAlign,
      boolean vertGrab, int vertSpan)
  {
    if (parent.getLayout() instanceof GridLayout)
    {
      return vertAlign(horzAlign(new GridData(), horzAlign, horzGrab, horzSpan), vertAlign, vertGrab, vertSpan);
    }

    return vertAlign(horzAlign(new TableWrapData(), horzAlign, horzGrab, horzSpan), vertAlign, vertGrab, vertSpan);
  }

  protected static <T> T heightHint(T layoutData, int hint)
  {
    if (layoutData instanceof GridData)
    {
      ((GridData)layoutData).heightHint = hint;
    }
    else
    {
      ((TableWrapData)layoutData).heightHint = hint;
    }

    return layoutData;
  }

  protected Control space(Composite parent, FormToolkit toolkit)
  {
    Control result = toolkit.createComposite(parent);
    result.setLayoutData(heightHint(layoutData(parent, SWT.FILL, false, 2), 15));
    return result;
  }

  protected OneToManyBlock oneToMany(Composite parent, FormToolkit toolkit, String label, EReference reference)
  {
    return oneToMany(parent, toolkit, label, reference, reference.getEReferenceType());
  }

  protected OneToManyBlock oneToMany(Composite parent, FormToolkit toolkit, String label, EReference reference,
      EClass itemType)
  {
    return oneToMany(parent, toolkit, label, reference, itemType, null);
  }

  protected OneToManyBlock oneToMany(Composite parent, FormToolkit toolkit, String label, EReference reference,
      EClass itemType, IFilter itemFilter)
  {
    toolkit.createLabel(parent, label).setLayoutData(layoutData(parent, SWT.LEFT, false, 2));
    Composite blockParent = toolkit.createComposite(parent);
    blockParent.setLayoutData(layoutData(parent, SWT.FILL, true, 2, SWT.FILL, true, 1));

    OneToManyBlock result = new OneToManyBlock(getContext(), getEditingDomain(), getAdapterFactory(),
        new OneToManyBlock.OneToManyConfiguration(getManagedForm(), reference, itemType, itemFilter));

    result.setEditorActionBars(getEditorActionBars());
    result.setInput(getValue());
    result.createControl(blockParent, toolkit);
    return result;
  }

  protected OneToManyTableBlock table(Composite parent, FormToolkit toolkit, String label,
      OneToManyTableBlock.ITableConfiguration config)
  {
    toolkit.createLabel(parent, label).setLayoutData(layoutData(parent, SWT.LEFT, false, 2));
    Composite blockParent = toolkit.createComposite(parent);
    blockParent.setLayoutData(layoutData(parent, SWT.FILL, true, 2, SWT.FILL, true, 1));

    OneToManyTableBlock result = new OneToManyTableBlock(getContext(), getEditingDomain(), getAdapterFactory(), config);

    result.setEditorActionBars(getEditorActionBars());
    result.setInput(getValue());
    result.createControl(blockParent, toolkit);
    return result;
  }

  protected Button checkbox(Composite parent, FormToolkit toolkit, String label, EAttribute attribute)
  {
    Button result = toolkit.createButton(
        createDecorationComposite(parent, toolkit, layoutData(parent, SWT.LEFT, false, 2)), label, SWT.CHECK);
    getContext().bindValue(WidgetProperties.enabled().observe(result),
        EMFEditObservables.observeDetailValue(getRealm(), getEditingDomain(), getValue(), attribute));
    getContext().bindValue(WidgetProperties.enabled().observe(result), getValue(), null,
        ObjectWritableConverter.createUpdateValueStrategy(attribute));

    addRevertDecoration(result, attribute);
    return result;
  }

  protected Button button(Composite parent, FormToolkit toolkit, String label, SelectionListener selectionListener)
  {
    Button result = toolkit.createButton(parent, label, SWT.PUSH);
    result.setLayoutData(layoutData(parent, SWT.LEFT, false, 2));

    getContext().bindValue(WidgetProperties.enabled().observe(result), getValue(), null,
        ObjectWritableConverter.createUpdateValueStrategy());

    result.addSelectionListener(selectionListener);
    return result;
  }

  protected ComboViewer combo(Composite parent, FormToolkit toolkit, String label, EAttribute attribute)
  {
    toolkit.createLabel(parent, label);
    ComboViewer result = new ComboViewer(
        createDecorationComposite(parent, toolkit, layoutData(parent, SWT.LEFT, false, 1)),
        SWT.READ_ONLY | SWT.DROP_DOWN);
    result.setLabelProvider(new AdapterFactoryLabelProvider(getAdapterFactory()));
    result.setContentProvider(new ArrayContentProvider());
    result.setInput(attribute.getEAttributeType().getInstanceClass().getEnumConstants());

    getContext().bindValue(ViewersObservables.observeSingleSelection(result),
        EMFEditObservables.observeDetailValue(getRealm(), getEditingDomain(), getValue(), attribute));
    getContext().bindValue(WidgetProperties.enabled().observe(result.getControl()), getValue(), null,
        ObjectWritableConverter.createUpdateValueStrategy(attribute));

    addRevertDecoration(result.getControl(), attribute);
    return result;
  }

  protected Composite createDecorationComposite(Composite parent, FormToolkit toolkit, Object layoutData)
  {
    Composite result = toolkit.createComposite(parent);
    result.setLayoutData(layoutData);

    GridLayout layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    layout.marginRight = 18; // 16 for image and 2 for offset
    result.setLayout(layout);

    return result;
  }

  protected void addRevertDecoration(final Control control, final EStructuralFeature feature)
  {
    final ControlDecoration decoration = new ControlDecoration(control, SWT.RIGHT | SWT.CENTER);
    decoration.hide();
    decoration.setDescriptionText(Messages.AbstractDetailsPage_3);
    decoration.setImage(ExtendedImageRegistry.getInstance()
        .getImage(URI.createPlatformPluginURI(OM.BUNDLE_ID + "/icons/full/elcl16/revert.gif", true))); //$NON-NLS-1$
    decoration.setMarginWidth(2);

    decoration.addSelectionListener(new SelectionAdapter()
    {
      @Override
      public void widgetSelected(SelectionEvent e)
      {
        Command command = SetCommand.create(getEditingDomain(), getInput(), feature, SetCommand.UNSET_VALUE);
        if (command.canExecute())
        {
          getEditingDomain().getCommandStack().execute(command);
        }
      }
    });

    control.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));

    // Show the decoration when the user hovers over the control and auto-hide after leaving the control
    MouseTrackListener showHideListener = new MouseTrackAdapter()
    {
      private Runnable hideRunnable;

      @Override
      public void mouseHover(MouseEvent e)
      {
        hideRunnable = null;
        if (control.isEnabled())
        {
          decoration.show();
        }
      }

      @Override
      public void mouseExit(MouseEvent e)
      {
        if (control.isEnabled())
        {
          hideRunnable = new Runnable()
          {

            public void run()
            {
              if (hideRunnable == this)
              {
                hideRunnable = null;
                decoration.hide();
              }
            }
          };

          control.getDisplay().timerExec(1000, hideRunnable);
        }
      }
    };

    control.addMouseTrackListener(showHideListener);
    control.getParent().addMouseTrackListener(showHideListener);
  }
}
