/*
 * Copyright (c) 2012, 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:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.emf.cdo.releng.apireports;

import org.eclipse.buckminster.core.actor.AbstractActor;
import org.eclipse.buckminster.core.actor.IActionContext;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.pde.api.tools.internal.ApiBaselineManager;
import org.eclipse.pde.api.tools.internal.comparator.DeltaXmlVisitor;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.Factory;
import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
import org.eclipse.pde.api.tools.internal.provisional.IApiDescription;
import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
import org.eclipse.pde.api.tools.internal.provisional.comparator.ApiComparator;
import org.eclipse.pde.api.tools.internal.provisional.comparator.ApiScope;
import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiScope;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Eike Stepper
 */
public class ApiReportsActor extends AbstractActor
{
  public ApiReportsActor()
  {
  }

  @Override
  protected IStatus internalPerform(IActionContext context, IProgressMonitor monitor) throws CoreException
  {
    Map<String, ? extends Object> properties = context.getAction().getActorProperties();
    String baselineName = (String)properties.get("baseline");
    if (baselineName == null || baselineName.length() == 0)
    {
      return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Baseline name not specified");
    }

    String exclusionPatterns = (String)properties.get("exclude");
    String reportFileName = System.getProperty("api.report", new File("api.xml").getAbsolutePath());

    SubMonitor progress = SubMonitor.convert(monitor, 100);
    progress.subTask("Collecting elements to compare");

    try
    {
      progress.subTask("Computing deltas...");
      File reportFile = new File(reportFileName);

      try
      {
        progress.worked(25);
        updateMonitor(progress);
        BufferedWriter writer = null;

        try
        {
          if (reportFile.exists())
          {
            reportFile.delete();
          }
          else
          {
            File parent = reportFile.getParentFile();
            if (!parent.exists() && !parent.mkdirs())
            {
              return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to create report directory structure");
            }
          }

          writer = new BufferedWriter(new FileWriter(reportFile));

          List<Object> projects = collectProjects(exclusionPatterns);
          IApiScope scope = walkStructureSelection(projects, monitor);
          IApiBaseline baseline = ApiBaselineManager.getManager().getApiBaseline(baselineName);
          if (baseline == null)
          {
            return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Baseline not found: " + baselineName);
          }

          IDelta delta = ApiComparator.compare(scope, baseline, VisibilityModifiers.API, false, true, monitor);
          if (delta != null)
          {
            progress.worked(25);
            updateMonitor(progress);

            DeltaXmlVisitor visitor = new DeltaXmlVisitor();
            delta.accept(visitor);

            writer.write(visitor.getXML());
            writer.flush();

            progress.worked(25);
          }
        }
        catch (IOException e)
        {
          ApiPlugin.log(e);
        }
        catch (CoreException e)
        {
          ApiPlugin.log(e);
        }
        finally
        {
          if (writer != null)
          {
            try
            {
              writer.close();
            }
            catch (IOException e)
            {
              // ignore
            }
          }
        }

        progress.worked(25);
        return Status.OK_STATUS;
      }
      catch (OperationCanceledException e)
      {
        // ignore
      }
    }
    finally
    {
      monitor.done();
    }

    return Status.CANCEL_STATUS;
  }

  private List<Object> collectProjects(String exclusionPatterns)
  {
    Pattern[] patterns = new Pattern[0];
    if (exclusionPatterns != null)
    {
      String[] split = exclusionPatterns.split(",");
      patterns = new Pattern[split.length];
      for (int i = 0; i < split.length; i++)
      {
        Pattern pattern = Pattern.compile(split[i]);
        patterns[i] = pattern;
      }
    }

    List<Object> result = new ArrayList<Object>();
    for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects())
    {
      if (project.isAccessible())
      {
        String name = project.getName();
        if (!isExcluded(patterns, name))
        {
          IJavaProject javaProject = JavaCore.create(project);
          if (javaProject != null)
          {
            result.add(javaProject);
          }
        }
      }
    }

    return result;
  }

  private boolean isExcluded(Pattern[] patterns, String name)
  {
    for (Pattern pattern : patterns)
    {
      Matcher matcher = pattern.matcher(name);
      if (matcher.matches())
      {
        return true;
      }
    }

    return false;
  }

  public static ApiScope walkStructureSelection(List<Object> projects, IProgressMonitor monitor)
  {
    ApiScope scope = new ApiScope();
    IApiBaseline workspaceBaseline = ApiBaselineManager.getManager().getWorkspaceBaseline();
    if (workspaceBaseline == null)
    {
      return scope;
    }

    Collections.sort(projects, new Comparator()
    {
      public int compare(Object o1, Object o2)
      {
        if (o1 instanceof IJavaElement && o2 instanceof IJavaElement)
        {
          IJavaElement element = (IJavaElement)o1;
          IJavaElement element2 = (IJavaElement)o2;
          return element.getElementType() - element2.getElementType();
        }

        return 0;
      }
    });

    for (Object project : projects)
    {
      if (project instanceof IJavaElement)
      {
        IJavaElement element = (IJavaElement)project;
        IJavaProject javaProject = element.getJavaProject();
        try
        {
          switch (element.getElementType())
          {
          case IJavaElement.COMPILATION_UNIT:
          {
            ICompilationUnit compilationUnit = (ICompilationUnit)element;
            IApiComponent apiComponent = workspaceBaseline.getApiComponent(javaProject.getElementName());
            if (apiComponent != null)
            {
              addElementFor(compilationUnit, apiComponent, scope);
            }

            break;
          }
          case IJavaElement.PACKAGE_FRAGMENT:
          {
            IPackageFragment fragment = (IPackageFragment)element;
            IApiComponent apiComponent = workspaceBaseline.getApiComponent(javaProject.getElementName());
            IPackageFragmentRoot packageFragmentRoot = (IPackageFragmentRoot)fragment
                .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
            boolean isArchive = false;
            if (packageFragmentRoot != null)
            {
              isArchive = packageFragmentRoot.isArchive();
            }

            if (apiComponent != null)
            {
              addElementFor(fragment, isArchive, apiComponent, scope);
            }

            break;
          }
          case IJavaElement.PACKAGE_FRAGMENT_ROOT:
          {
            IPackageFragmentRoot fragmentRoot = (IPackageFragmentRoot)element;
            IApiComponent apiComponent = workspaceBaseline.getApiComponent(javaProject.getElementName());
            if (apiComponent != null)
            {
              addElementFor(fragmentRoot, apiComponent, scope);
            }

            break;
          }
          case IJavaElement.JAVA_PROJECT:
            IApiComponent apiComponent = workspaceBaseline.getApiComponent(javaProject.getElementName());
            if (apiComponent != null)
            {
              scope.addElement(apiComponent);
            }

            break;
          }
        }
        catch (JavaModelException e)
        {
          ApiPlugin.log(e);
        }
        catch (CoreException e)
        {
          ApiPlugin.log(e);
        }
      }
    }

    return scope;
  }

  private static void addElementFor(IPackageFragmentRoot fragmentRoot, IApiComponent apiComponent, ApiScope scope)
      throws JavaModelException, CoreException
  {
    boolean isArchive = fragmentRoot.isArchive();
    IJavaElement[] packageFragments = fragmentRoot.getChildren();
    for (int j = 0, max2 = packageFragments.length; j < max2; j++)
    {
      IPackageFragment packageFragment = (IPackageFragment)packageFragments[j];
      addElementFor(packageFragment, isArchive, apiComponent, scope);
    }
  }

  private static void addElementFor(IPackageFragment packageFragment, boolean isArchive, IApiComponent apiComponent,
      ApiScope scope) throws JavaModelException, CoreException
  {
    // add package fragment elements only if this is an API package
    IApiDescription apiDescription = apiComponent.getApiDescription();
    IApiAnnotations annotations = apiDescription
        .resolveAnnotations(Factory.packageDescriptor(packageFragment.getElementName()));
    if (annotations == null || !VisibilityModifiers.isAPI(annotations.getVisibility()))
    {
      return;
    }

    if (isArchive)
    {
      IClassFile[] classFiles = packageFragment.getClassFiles();
      for (int i = 0, max = classFiles.length; i < max; i++)
      {
        addElementFor(classFiles[i], apiComponent, scope);
      }
    }
    else
    {
      ICompilationUnit[] units = packageFragment.getCompilationUnits();
      for (int i = 0, max = units.length; i < max; i++)
      {
        addElementFor(units[i], apiComponent, scope);
      }
    }
  }

  private static void addElementFor(IClassFile classFile, IApiComponent apiComponent, ApiScope scope)
  {
    try
    {
      IApiTypeRoot typeRoot = apiComponent.findTypeRoot(classFile.getType().getFullyQualifiedName());
      if (typeRoot != null)
      {
        scope.addElement(typeRoot);
      }
    }
    catch (CoreException e)
    {
      ApiPlugin.log(e);
    }
  }

  private static void addElementFor(ICompilationUnit compilationUnit, IApiComponent component, ApiScope scope)
      throws JavaModelException
  {
    IType[] types = compilationUnit.getTypes();
    for (int i = 0, max = types.length; i < max; i++)
    {
      try
      {
        IApiTypeRoot typeRoot = component.findTypeRoot(types[i].getFullyQualifiedName());
        if (typeRoot != null)
        {
          scope.addElement(typeRoot);
        }
      }
      catch (CoreException e)
      {
        ApiPlugin.log(e);
      }
    }
  }

  private static void updateMonitor(IProgressMonitor monitor, int work) throws OperationCanceledException
  {
    if (monitor == null)
    {
      return;
    }

    if (monitor.isCanceled())
    {
      throw new OperationCanceledException();
    }

    monitor.worked(work);
  }

  private static void updateMonitor(IProgressMonitor monitor) throws OperationCanceledException
  {
    updateMonitor(monitor, 0);
  }
}
