/*******************************************************************************
 * Copyright (c) 2011 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *      Sonatype, Inc. - initial API and implementation
 *      Andrew Eisenberg - adapted for workspace preferences
 *******************************************************************************/

package org.eclipse.m2e.core.ui.internal.preferences;

import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
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.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.PlatformUI;

import org.codehaus.plexus.util.xml.Xpp3Dom;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;

import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.internal.lifecyclemapping.LifecycleMappingFactory;
import org.eclipse.m2e.core.internal.lifecyclemapping.LifecycleMappingResult;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.LifecycleMappingMetadata;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.LifecycleMappingMetadataSource;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.PluginExecutionFilter;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.PluginExecutionMetadata;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.io.xpp3.LifecycleMappingMetadataSourceXpp3Writer;
import org.eclipse.m2e.core.internal.project.registry.MavenProjectFacade;
import org.eclipse.m2e.core.lifecyclemapping.model.IPluginExecutionMetadata;
import org.eclipse.m2e.core.lifecyclemapping.model.PluginExecutionAction;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.IMavenProjectRegistry;
import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
import org.eclipse.m2e.core.ui.internal.MavenImages;
import org.eclipse.m2e.core.ui.internal.Messages;


@SuppressWarnings("restriction")
class LifecycleMappingsViewer {
  private static final Logger log = LoggerFactory.getLogger(LifecycleMappingsViewer.class);

  /*package*/TreeViewer mappingsTreeViewer;

  /*package*/boolean showPhases = false;

  /*package*/boolean showIgnoredExecutions = true;

  /*package*/Map<MojoExecutionKey, List<IPluginExecutionMetadata>> mappings;

  /*package*/Map<String, List<MojoExecutionKey>> phases;

  private Shell shell;

  void updateMappingsTreeViewer() {
    mappingsTreeViewer.refresh();
    if(showPhases) {
      // reveal non-empty mappings
      mappingsTreeViewer.collapseAll();
      for(Map.Entry<MojoExecutionKey, List<IPluginExecutionMetadata>> entry : mappings.entrySet()) {
        boolean expand = false;
        if(isErrorMapping(entry.getKey())) {
          expand = true;
        } else {
          expand = !isIgnoreMapping(entry.getKey(), entry.getValue());
        }
        if(expand) {
          mappingsTreeViewer.expandToLevel(entry.getKey().getLifecyclePhase(), AbstractTreeViewer.ALL_LEVELS);
        }
      }
    }
    // auto-size all columns
    for(TreeColumn column : mappingsTreeViewer.getTree().getColumns()) {
      column.pack();
    }
  }

  /**
   * @wbp.parser.entryPoint
   */
  public Composite createContents(Composite parent) {
    Composite container = new Composite(parent, SWT.NULL);
    GridLayout gl_container = new GridLayout(1, false);
    gl_container.marginWidth = 0;
    gl_container.marginHeight = 0;
    container.setLayout(gl_container);

    Composite optionsComposit = new Composite(container, SWT.NONE);
    GridLayout gl_optionsComposit = new GridLayout(3, false);
    gl_optionsComposit.marginWidth = 0;
    gl_optionsComposit.marginHeight = 0;
    optionsComposit.setLayout(gl_optionsComposit);
    optionsComposit.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

    final Button btnShowPhases = new Button(optionsComposit, SWT.CHECK);
    btnShowPhases.setSelection(showPhases);
    btnShowPhases.setText(Messages.LifecycleMappingPropertyPage_showLIfecyclePhases);

    final Button btnShowIgnored = new Button(optionsComposit, SWT.CHECK);
    btnShowIgnored.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        showIgnoredExecutions = btnShowIgnored.getSelection();
        updateMappingsTreeViewer();
      }
    });
    btnShowIgnored.setSelection(showIgnoredExecutions);
    btnShowIgnored.setText(Messages.LifecycleMappingPropertyPage_mntmShowIgnoredExecutions_text);
    final Action actExpandAll = new Action(Messages.LifecycleMappingPropertyPage_mntmExpandAll_text,
        MavenImages.EXPANDALL) {
      public void run() {
        mappingsTreeViewer.expandAll();
      };
    };
    actExpandAll.setEnabled(showPhases);
    final Action actCollapseAll = new Action(Messages.LifecycleMappingPropertyPage_mntmCollapseAll_text,
        MavenImages.COLLAPSEALL) {
      public void run() {
        mappingsTreeViewer.collapseAll();
      };
    };
    actCollapseAll.setEnabled(showPhases);

    Composite toolbarComposite = new Composite(optionsComposit, SWT.NONE);
    toolbarComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
    GridLayout gl_toolbarComposite = new GridLayout(1, false);
    gl_toolbarComposite.marginWidth = 0;
    gl_toolbarComposite.marginHeight = 0;
    toolbarComposite.setLayout(gl_toolbarComposite);

    ToolBar toolBar = new ToolBar(toolbarComposite, SWT.FLAT | SWT.RIGHT);
    ToolBarManager toolBarManager = new ToolBarManager(toolBar);
    toolBarManager.add(actExpandAll);
    toolBarManager.add(actCollapseAll);
    toolBarManager.update(true);

    btnShowPhases.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        showPhases = btnShowPhases.getSelection();
        actExpandAll.setEnabled(showPhases);
        actCollapseAll.setEnabled(showPhases);
        updateMappingsTreeViewer();
      }
    });

    mappingsTreeViewer = new TreeViewer(container, SWT.BORDER);
    Tree tree = mappingsTreeViewer.getTree();
    tree.setHeaderVisible(true);
    tree.setLinesVisible(true);
    tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

    TreeViewerColumn treeViewerColumn = new TreeViewerColumn(mappingsTreeViewer, SWT.NONE);
    TreeColumn trclmnGoal = treeViewerColumn.getColumn();
    trclmnGoal.setWidth(100);
    trclmnGoal.setText(Messages.LifecycleMappingPropertyPage_pluginExecution);

    TreeViewerColumn treeViewerColumn_1 = new TreeViewerColumn(mappingsTreeViewer, SWT.NONE);
    TreeColumn trclmnNewColumn = treeViewerColumn_1.getColumn();
    trclmnNewColumn.setWidth(100);
    trclmnNewColumn.setText(Messages.LifecycleMappingPropertyPage_mapping);

    TreeViewerColumn treeViewerColumn_2 = new TreeViewerColumn(mappingsTreeViewer, SWT.NONE);
    TreeColumn trclmnSource = treeViewerColumn_2.getColumn();
    trclmnSource.setWidth(100);
    trclmnSource.setText(Messages.LifecycleMappingsViewer_trclmnSource_text);

    mappingsTreeViewer.setContentProvider(new ITreeContentProvider() {

      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      }

      public void dispose() {
      }

      public boolean hasChildren(Object element) {
        return getChildren(element) != null;
      }

      public Object getParent(Object element) {
        return null;
      }

      public Object[] getElements(Object inputElement) {
        if(showPhases) {
          return phases.keySet().toArray();
        }
        Set<MojoExecutionKey> executions;
        if(showIgnoredExecutions) {
          executions = mappings.keySet();
        } else {
          executions = new LinkedHashSet<MojoExecutionKey>();
          for(Map.Entry<MojoExecutionKey, List<IPluginExecutionMetadata>> entry : mappings.entrySet()) {
            if(!isIgnoreMapping(entry.getKey(), entry.getValue())) {
              executions.add(entry.getKey());
            }
          }
        }
        return executions.toArray();
      }

      public Object[] getChildren(Object parentElement) {
        List<MojoExecutionKey> executions = phases.get(parentElement);
        if(executions == null || executions.isEmpty()) {
          return null;
        }
        if(showIgnoredExecutions) {
          return executions.toArray();
        }
        // filter out ignored executions
        executions = new ArrayList<MojoExecutionKey>(executions); // clone
        Iterator<MojoExecutionKey> iter = executions.iterator();
        while(iter.hasNext()) {
          MojoExecutionKey execution = iter.next();
          if(isIgnoreMapping(execution, mappings.get(execution))) {
            iter.remove();
          }
        }
        return !executions.isEmpty() ? executions.toArray() : null;
      }
    });

    mappingsTreeViewer.setLabelProvider(new ITableLabelProvider() {

      public void addListener(ILabelProviderListener listener) {
      }

      public void dispose() {
      }

      public boolean isLabelProperty(Object element, String property) {
        return false;
      }

      public void removeListener(ILabelProviderListener listener) {
      }

      public Image getColumnImage(Object element, int columnIndex) {
        if(columnIndex == 0 && element instanceof MojoExecutionKey) {
          return isErrorMapping((MojoExecutionKey) element) ? MavenImages.IMG_ERROR : MavenImages.IMG_PASSED;
        }
        return null;
      }

      public String getColumnText(Object element, int columnIndex) {
        if(element instanceof MojoExecutionKey) {
          MojoExecutionKey execution = (MojoExecutionKey) element;
          switch(columnIndex) {
            case 0:
              return LifecycleMappingsViewer.this.toString(execution);
            case 1:
              return LifecycleMappingsViewer.this.toString(execution, mappings.get(execution));
            case 2:
              return getSourcelabel(execution, mappings.get(execution), false);
          }
        }
        return columnIndex == 0 ? element.toString() : null;
      }
    });

    Composite actionsComposite = new Composite(container, SWT.NONE);
    actionsComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
    actionsComposite.setLayout(new RowLayout(SWT.HORIZONTAL));

    Button btnCopyToClipboard = new Button(actionsComposite, SWT.NONE);
    btnCopyToClipboard.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        copyToClipboard();
      }
    });
    btnCopyToClipboard.setText(Messages.LifecycleMappingPropertyPage_copyToClipboard);

    mappingsTreeViewer.setInput(phases);

    updateMappingsTreeViewer();
    return container;
  }

  void copyToClipboard() {
    if(mappings == null) {
      return;
    }

    LifecycleMappingMetadata meta = new LifecycleMappingMetadata();

    for(Map.Entry<MojoExecutionKey, List<IPluginExecutionMetadata>> entry : this.mappings.entrySet()) {
      MojoExecutionKey execution = entry.getKey();
      List<IPluginExecutionMetadata> mappings = entry.getValue();
      if(mappings != null && !mappings.isEmpty()) {
        for(IPluginExecutionMetadata mapping : mappings) {
          PluginExecutionMetadata clone = ((PluginExecutionMetadata) mapping).clone();
          setMappingSource(execution, mappings, clone);
          meta.addPluginExecution(clone);
        }
      } else {
        PluginExecutionFilter filter = new PluginExecutionFilter(execution.getGroupId(), execution.getArtifactId(),
            execution.getVersion(), execution.getGoal());

        PluginExecutionMetadata mapping = new PluginExecutionMetadata();
        mapping.setFilter(filter);

        Xpp3Dom actionDom;
        if(LifecycleMappingFactory.isInterestingPhase(entry.getKey().getLifecyclePhase())) {
          actionDom = new Xpp3Dom(PluginExecutionAction.error.toString());
        } else {
          actionDom = new Xpp3Dom(PluginExecutionAction.ignore.toString());
        }
        mapping.setActionDom(actionDom);

        setMappingSource(execution, mappings, mapping);

        meta.addPluginExecution(mapping);
      }
    }

    LifecycleMappingMetadataSource xml = new LifecycleMappingMetadataSource();
    xml.addLifecycleMapping(meta);

    StringWriter buf = new StringWriter();
    try {
      new LifecycleMappingMetadataSourceXpp3Writer().write(buf, xml);

      Clipboard clipboard = new Clipboard(shell.getDisplay());

      Object[] data = new Object[] {buf.toString()};
      Transfer[] dataTypes = new Transfer[] {TextTransfer.getInstance()};

      clipboard.setContents(data, dataTypes);

      clipboard.dispose();
    } catch(IOException ex) {
      // TODO log
    }
  }

  private void setMappingSource(MojoExecutionKey execution, List<IPluginExecutionMetadata> mappings,
      PluginExecutionMetadata clone) {
    clone.setComment("source: " + getSourcelabel(execution, mappings, true)); //$NON-NLS-1$
  }

  boolean isErrorMapping(MojoExecutionKey execution) {
    List<IPluginExecutionMetadata> mappings = this.mappings.get(execution);
    if(mappings == null || mappings.isEmpty()) {
      return LifecycleMappingFactory.isInterestingPhase(execution.getLifecyclePhase());
    }
    for(IPluginExecutionMetadata mapping : mappings) {
      if(PluginExecutionAction.error == mapping.getAction()) {
        return true;
      }
    }
    return false;
  }

  boolean isIgnoreMapping(MojoExecutionKey execution, List<IPluginExecutionMetadata> mappings) {
    if(mappings == null || mappings.isEmpty()) {
      return !LifecycleMappingFactory.isInterestingPhase(execution.getLifecyclePhase());
    }
    for(IPluginExecutionMetadata mapping : mappings) {
      if(PluginExecutionAction.ignore != mapping.getAction()) {
        return false;
      }
    }
    return true;
  }

  String toString(MojoExecutionKey execution, List<IPluginExecutionMetadata> mappings) {
    StringBuilder sb = new StringBuilder();
    if(mappings != null && !mappings.isEmpty()) {
      for(IPluginExecutionMetadata mapping : mappings) {
        if(sb.length() > 0) {
          sb.append(',');
        }
        sb.append(mapping.getAction().toString());
      }
    } else {
      if(LifecycleMappingFactory.isInterestingPhase(execution.getLifecyclePhase())) {
        sb.append(PluginExecutionAction.error.toString());
      } else {
        sb.append(PluginExecutionAction.ignore.toString());
      }
    }
    return sb.toString();
  }

  String getSourcelabel(MojoExecutionKey execution, List<IPluginExecutionMetadata> mappings, boolean detailed) {
    LinkedHashSet<String> sources = new LinkedHashSet<String>();
    if(mappings != null && !mappings.isEmpty()) {
      for(IPluginExecutionMetadata mapping : mappings) {
        LifecycleMappingMetadataSource metadata = ((PluginExecutionMetadata) mapping).getSource();
        if(metadata != null) {
          Object source = metadata.getSource();
          if(source instanceof String) {
            sources.add((String) source);
          } else if(source instanceof Artifact) {
            sources.add(getSourceLabel((Artifact) source, detailed));
          } else if(source instanceof MavenProject) {
            sources.add(getSourceLabel((MavenProject) source, detailed));
          } else if(source instanceof Bundle) {
            sources.add(getSourceLabel((Bundle) source, detailed));
          } else {
            sources.add("unknown"); //$NON-NLS-1$
          }
        }
      }
    } else {
      if(!LifecycleMappingFactory.isInterestingPhase(execution.getLifecyclePhase())) {
        sources.add("uninteresting"); //$NON-NLS-1$
      }
    }
    StringBuilder sb = new StringBuilder();
    for(String source : sources) {
      if(sb.length() > 0) {
        sb.append(',');
      }
      sb.append(source);
    }
    return sb.toString();
  }

  private String getSourceLabel(Bundle bundle, boolean detailed) {
    StringBuilder sb = new StringBuilder("extension"); //$NON-NLS-1$
    if(detailed) {
      sb.append('(').append(bundle.getSymbolicName()).append('_').append(bundle.getVersion()).append(')');
    }
    return sb.toString();
  }

  private String getSourceLabel(MavenProject project, boolean detailed) {
    StringBuilder sb = new StringBuilder("pom"); //$NON-NLS-1$
    if(detailed) {
      sb.append('(').append(project.toString()).append(')');
    }
    return sb.toString();
  }

  private String getSourceLabel(Artifact plugin, boolean detailed) {
    StringBuilder sb = new StringBuilder("maven-plugin"); //$NON-NLS-1$
    if(detailed) {
      sb.append('(').append(plugin.toString()).append(')');
    }
    return sb.toString();
  }

  String toString(MojoExecutionKey execution) {
    // http://maven.apache.org/guides/plugin/guide-java-plugin-development.html#Shortening_the_Command_Line

    StringBuilder sb = new StringBuilder();

    // TODO show groupId, but only if not a known plugin groupId

    // shorten artifactId
    String artifactId = execution.getArtifactId();
    if(artifactId.endsWith("-maven-plugin")) { //$NON-NLS-1$
      artifactId = artifactId.substring(0, artifactId.length() - "-maven-plugin".length()); //$NON-NLS-1$
    } else if(artifactId.startsWith("maven-") && artifactId.endsWith("-plugin")) { //$NON-NLS-1$ //$NON-NLS-2$
      artifactId = artifactId.substring("maven-".length(), artifactId.length() - "-plugin".length()); //$NON-NLS-1$ //$NON-NLS-2$
    }

    sb.append(artifactId).append(':').append(execution.getGoal());

    // only show execution id if necessary
    int count = 0;
    for(MojoExecutionKey other : mappings.keySet()) {
      if(eq(execution.getGroupId(), other.getGroupId()) && eq(execution.getArtifactId(), other.getArtifactId())
          && eq(execution.getGoal(), other.getGoal())) {
        count++ ;
      }
    }
    if(count > 1) {
      sb.append(" (").append(execution.getExecutionId()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
    }
    return sb.toString();
  }

  static <T> boolean eq(T a, T b) {
    return a != null ? a.equals(b) : b == null;
  }

  public void setTarget(final IProject project) {
    if(project == null) {
      // TODO FIXADE find the mojo execution mapping for the workspace...How do I do this?
    } else {
      try {
        PlatformUI.getWorkbench().getProgressService().run(false, false, monitor -> {
          final IMavenProjectRegistry projectRegistry = MavenPlugin.getMavenProjectRegistry();
          final IMavenProjectFacade facade = projectRegistry.getProject(project);
          if(facade == null) {
            return;
          }
          try {
            projectRegistry.execute(facade, (context, monitor1) -> {
              MavenProject mavenProject = facade.getMavenProject(monitor1);
              List<MojoExecution> mojoExecutions = ((MavenProjectFacade) facade).getMojoExecutions(monitor1);
              LifecycleMappingResult mappingResult = LifecycleMappingFactory.calculateLifecycleMapping(mavenProject,
                  mojoExecutions, facade.getResolverConfiguration().getLifecycleMappingId(), monitor1);
              mappings = mappingResult.getMojoExecutionMapping();
              return null;
            }, monitor);
          } catch(CoreException ex) {
            throw new InvocationTargetException(ex);
          }
        });
      } catch(InvocationTargetException ex) {
        log.error(ex.getMessage(), ex);
      } catch(InterruptedException ex) {
        log.error(ex.getMessage(), ex);
      }
    }
    phases = new LinkedHashMap<String, List<MojoExecutionKey>>();
    if(mappings != null) {
      for(MojoExecutionKey execution : mappings.keySet()) {
        List<MojoExecutionKey> executions = phases.get(execution.getLifecyclePhase());
        if(executions == null) {
          executions = new ArrayList<MojoExecutionKey>();
          phases.put(execution.getLifecyclePhase(), executions);
        }
        executions.add(execution);
      }
    }
  }

  /**
   * @param shell
   */
  public void setShell(Shell shell) {
    this.shell = shell;
  }

  protected boolean isValid() {
    return mappings != null;
  }
}
