/*
 * Copyright (c) 2004 - 2012 Eike Stepper (Loehne, 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 promoter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import promoter.util.IO;
import promoter.util.XMLOutput;

/**
 * @author Eike Stepper
 */
public class ReleaseNotesGenerator extends PromoterComponent
{
  private SourceCodeManager scm;

  private IssueManager issueManager;

  public ReleaseNotesGenerator()
  {
  }

  public synchronized void generateReleaseNotes(List<BuildInfo> buildInfos)
  {
    scm = getPromoter().createSourceCodeManager();
    issueManager = getPromoter().createIssueManager();

    for (ReleaseNotesStream stream : getStreams(buildInfos))
    {
      if (!stream.isDisabled())
      {
        generateReleaseNotes(stream);
      }
    }

    issueManager = null;
    scm = null;
  }

  protected void generateReleaseNotes(ReleaseNotesStream stream)
  {
    BuildInfo[] buildInfos = getBuildInfos(stream);
    for (int i = 0; i < buildInfos.length; i++)
    {
      generateReleaseNotes(stream, buildInfos, i);
    }
  }

  protected void generateReleaseNotes(ReleaseNotesStream stream, BuildInfo[] buildInfos, int i)
  {
    BuildInfo buildInfo = buildInfos[i];
    String qualifier = buildInfo.getQualifier();

    File drop = buildInfo.getDrop();
    File relnotesXML = new File(drop, "relnotes.xml");
    File relnotesHTML = new File(drop, "relnotes.html");
    if (!relnotesXML.exists() || !relnotesHTML.exists())
    {
      System.out.println();
      System.out.println("Generating release notes for " + qualifier);

      BuildInfo previousBuildInfo = getPreviousBuildInfo(buildInfos, i);
      String fromRevision = previousBuildInfo == null ? stream.getFirstRevision() : previousBuildInfo.getRelnotesRevision();
      String toRevision = buildInfo.getRevision();

      List<Issue> issues = new ArrayList<>(getIssues(buildInfo, fromRevision, toRevision));
      sortIssues(issues);

      generateReleaseNotesXML(buildInfo, previousBuildInfo, fromRevision, toRevision, issues, relnotesXML);
      generateReleaseNotesHTML(buildInfo, previousBuildInfo, fromRevision, toRevision, issues, relnotesHTML);
    }
  }

  protected void generateReleaseNotesXML(BuildInfo buildInfo, BuildInfo previousBuildInfo, String fromRevision, String toRevision, List<Issue> issues,
      File relnotesXML)
  {
    OutputStream out = null;

    try
    {
      out = new FileOutputStream(relnotesXML);
      XMLOutput xml = new XMLOutput(out);

      xml.element("relnotes");
      xml.attribute("stream", buildInfo.getStream());
      xml.attribute("drop", buildInfo.getQualifier());
      xml.attribute("revision", toRevision);
      if (previousBuildInfo != null)
      {
        xml.attribute("previousDrop", previousBuildInfo.getQualifier());
      }

      xml.attribute("previousRevision", fromRevision);
      xml.push();

      for (Issue issue : issues)
      {
        xml.element("issue");
        xml.attribute("url", issueManager.getURL(issue));
        xml.attribute("id", issue.getID());
        xml.attribute("title", issue.getTitle());
        xml.attribute("severity", issue.getSeverity());
        xml.attribute("component", issue.getComponent());
        xml.attribute("version", issue.getVersion());
      }

      xml.pop();
      xml.done();
    }
    catch (Exception ex)
    {
      throw new RuntimeException(ex);
    }
    finally
    {
      IO.close(out);
    }
  }

  protected void generateReleaseNotesHTML(BuildInfo buildInfo, BuildInfo previousBuildInfo, String fromRevision, String toRevision, List<Issue> issues,
      File relnotesHTML)
  {
    PrintStream out = null;

    try
    {
      List<IssueComponent> components = new ArrayList<>();
      addIssueComponent(components, "cdo.core", "CDO Model Repository (Core)");
      addIssueComponent(components, "cdo.legacy", "CDO Model Repository (Legacy Mode)");
      addIssueComponent(components, "cdo.ui", "CDO Model Repository (User Interface)");
      addIssueComponent(components, "cdo.db", "CDO Model Repository (JDBC Support)");
      addIssueComponent(components, "cdo.dawn", "CDO Dawn");
      addIssueComponent(components, "cdo.net4j", "Net4j Signalling Platform and Utilities");
      addIssueComponent(components, "cdo.net4j.ui", "Net4j User Interface");
      addIssueComponent(components, "cdo.net4j.db", "Net4j DB Framework");
      addIssueComponent(components, "cdo.docs", "Documentation");
      addIssueComponent(components, "cdo.releng", "Release Engineering");
      IssueComponent other = addIssueComponent(components, "", "Other");

      for (Issue issue : issues)
      {
        String name = issue.getComponent();
        IssueComponent component = getIssueComponent(components, name);
        if (component == null)
        {
          component = other;
        }

        component.addIssue(issue);
      }

      for (Iterator<IssueComponent> it = components.iterator(); it.hasNext();)
      {
        IssueComponent component = it.next();
        if (component.isEmpty())
        {
          it.remove();
        }
      }

      out = new PrintStream(relnotesHTML);

      String qualifier = buildInfo.getQualifier();
      out.println("<!DOCTYPE html>");
      out.println("<html>");
      out.println("<head>");
      out.println("  <title>Release Notes for CDO " + qualifier + "</title>");
      out.println("</head>");
      out.println();
      out.println("<body style=\"font-family:Arial; font-size:small;\">");
      out.println(
          "<h1>Release Notes for CDO <a href=\"https://www.eclipse.org/cdo/downloads/#" + qualifier.replace('-', '_') + "\">" + qualifier + "</a></h1>");

      out.println("<p>");
      out.println("These release notes have been generated from the commit log of the <a href=\"https://www.eclipse.org/cdo/downloads/#releases_"
          + buildInfo.getStream().replace('.', '_') + "\">" + buildInfo.getStream() + "</a> stream and the associated bugzillas.");
      out.print("<br/>The first commit is " + fromRevision);
      if (previousBuildInfo != null)
      {
        out.println(" in the <a href=\"http://git.eclipse.org/c/cdo/cdo.git/?h=" + previousBuildInfo.getBranch().replaceAll("/", "%2F") + "\">"
            + previousBuildInfo.getBranch() + "</a> branch.");
      }
      else
      {
        out.println(" in the <a href=\"http://git.eclipse.org/c/cdo/cdo.git/?h=master\">master</a> branch.");
      }

      out.println("<br/>The last commit is " + toRevision + " in the <a href=\"" + "http://git.eclipse.org/c/cdo/cdo.git/?h="
          + buildInfo.getBranch().replaceAll("/", "%2F") + "\">" + buildInfo.getBranch() + "</a> branch.");

      previousBuildNote(out, buildInfo, previousBuildInfo);
      out.println("</p>");

      if (!components.isEmpty())
      {
        out.println("<h3>Table of Contents</h3>");
        out.println("<ul>");
        for (IssueComponent component : components)
        {
          component.renderTOC(out);
        }

        out.println("</ul>");

        for (IssueComponent component : components)
        {
          component.renderHTML(out);
        }

        previousBuildNote(out, buildInfo, previousBuildInfo);
      }
      else
      {
        out.println("<h3>This build does not contain any tracked enhancements or bug fixes.</h3>");
        out.println("It may contain other changes, though.");
      }

      out.println("</body>");
      out.println("</html>");
    }
    catch (Exception ex)
    {
      throw new RuntimeException(ex);
    }
    finally
    {
      IO.close(out);
    }
  }

  protected void previousBuildNote(PrintStream out, BuildInfo buildInfo, BuildInfo previousBuildInfo)
  {
    out.print("<br/>");
    if (previousBuildInfo != null)
    {
      String q = previousBuildInfo.getQualifier();
      out.println("The previous build of the " + buildInfo.getStream() + " stream is <a href=\"https://www.eclipse.org/cdo/downloads/#" + q.replace('-', '_')
          + "\">" + q + "</a>.");
    }
    else
    {
      out.println("This is the first build of the " + buildInfo.getStream() + " stream.");
    }
  }

  protected IssueComponent addIssueComponent(List<IssueComponent> components, String name, String label)
  {
    IssueComponent component = new IssueComponent(name, label);
    components.add(component);
    return component;
  }

  protected IssueComponent getIssueComponent(List<IssueComponent> components, String name)
  {
    for (IssueComponent component : components)
    {
      if (component.getName().equals(name))
      {
        return component;
      }
    }

    return null;
  }

  protected Collection<ReleaseNotesStream> getStreams(List<BuildInfo> buildInfos)
  {
    Map<String, ReleaseNotesStream> streams = new HashMap<>();
    for (BuildInfo buildInfo : buildInfos)
    {
      String name = buildInfo.getStream();
      if (name != null && name.length() != 0)
      {
        ReleaseNotesStream stream = streams.get(name);
        if (stream == null)
        {
          stream = new ReleaseNotesStream(name);
          streams.put(name, stream);
        }

        stream.getBuildInfos().add(buildInfo);
      }
    }

    return streams.values();
  }

  protected BuildInfo[] getBuildInfos(ReleaseNotesStream stream)
  {
    List<BuildInfo> buildInfos = stream.getBuildInfos();
    Collections.sort(buildInfos, (bi1, bi2) -> bi1.getTimestamp().compareTo(bi2.getTimestamp()));

    return buildInfos.toArray(new BuildInfo[buildInfos.size()]);
  }

  protected BuildInfo getPreviousBuildInfo(BuildInfo[] buildInfos, int current)
  {
    String currentBuildType = buildInfos[current].getType();
    String previousBuildTypes = getPreviousBuildTypes(currentBuildType);

    for (int i = current - 1; i >= 0; --i)
    {
      BuildInfo previousBuildInfo = buildInfos[i];
      String previousBuildType = previousBuildInfo.getType();
      if (previousBuildTypes.contains(previousBuildType))
      {
        return previousBuildInfo;
      }
    }

    // Use stream start
    return null;
  }

  protected String getPreviousBuildTypes(String currentBuildType)
  {
    if ("N".equals(currentBuildType))
    {
      return "NIMSR";
    }

    if ("I".equals(currentBuildType) || "M".equals(currentBuildType))
    {
      return "IMSR";
    }

    if ("S".equals(currentBuildType))
    {
      return "SR";
    }

    if ("R".equals(currentBuildType))
    {
      return "R";
    }

    throw new RuntimeException("Unrecognized build type: " + currentBuildType);
  }

  protected Set<Issue> getIssues(BuildInfo buildInfo, String fromRevision, String toRevision)
  {
    final Set<Issue> issues = new HashSet<>();

    if (!fromRevision.equals(toRevision))
    {
      String branch = buildInfo.getBranch();
      scm.handleLogEntries(branch, fromRevision, toRevision, false, logEntry -> {
        String message = logEntry.getMessage();
        String id = issueManager.parseID(message);
        if (id != null && id.length() != 0)
        {
          Issue issue = issueManager.getIssue(id);
          if (issue != null)
          {
            if (issues.add(issue))
            {
              System.out.println("   " + issue.getID() + ": " + issue.getTitle() + " --> " + issue.getSeverity());
            }
          }
        }
      });
    }

    return issues;
  }

  protected void sortIssues(List<Issue> issues)
  {
    Collections.sort(issues, issueManager);
  }

  /**
   * @author Eike Stepper
   */
  private final class IssueComponent
  {
    private final String name;

    private final String label;

    private final List<Issue> enhancements = new ArrayList<>();

    private final List<Issue> fixes = new ArrayList<>();

    public IssueComponent(String name, String label)
    {
      this.name = name;
      this.label = label;
    }

    public String getName()
    {
      return name;
    }

    public boolean isEmpty()
    {
      return enhancements.isEmpty() && fixes.isEmpty();
    }

    public void addIssue(Issue issue)
    {
      if (issueManager.getSeverity(issue) == 0)
      {
        enhancements.add(issue);
      }
      else
      {
        fixes.add(issue);
      }
    }

    public void renderTOC(PrintStream out)
    {
      if (isEmpty())
      {
        return;
      }

      out.println("<a name=\"" + name + "\"></a>");
      out.println("<li><a href=\"#" + name + "\">" + label + "</a>");
    }

    public void renderHTML(PrintStream out)
    {
      if (isEmpty())
      {
        return;
      }

      out.println("<a name=\"" + name + "\"></a>");
      out.println("<h2>" + label + "</h2>");
      out.println("<div style=\"margin-left:20px;\">");

      if (!enhancements.isEmpty())
      {
        out.println("<h3>Enhancements</h3>");
        out.println("<div style=\"margin-left:20px;\">");
        renderHTML(out, enhancements);
        out.println("</div>");
      }

      if (!fixes.isEmpty())
      {
        Collections.sort(fixes, (i1, i2) -> {
          Integer s1 = issueManager.getSeverity(i1);
          Integer s2 = issueManager.getSeverity(i2);
          return -s1.compareTo(s2);
        });

        out.println("<h3>Bug Fixes</h3>");
        out.println("<div style=\"margin-left:20px;\">");
        renderHTML(out, fixes);
        out.println("</div>");
      }

      out.println("</div>");
    }

    private void renderHTML(PrintStream out, List<Issue> issues)
    {
      for (Issue issue : issues)
      {
        String severity = issue.getSeverity();
        String url = issueManager.getURL(issue);
        String title = issue.getTitle().replaceAll("<", "&lt;").replaceAll("\"", "&quot;");

        out.print("<img src=\"../../images/" + severity + ".gif\" alt=\"" + severity + "\">&nbsp;");
        out.print("[<a href=\"" + url + "\">" + issue.getID() + "</a>]&nbsp;" + title);
        out.print("&nbsp;&nbsp;&nbsp;&nbsp;<font color=\"#aaaaaa\"><i>" + issue.getStatus().toLowerCase() + " in " + issue.getVersion() + "</i></font>");
        out.println("<br/>");
      }
    }
  }
}
