// Copyright (C) 2015 Advanced Micro Devices, Inc.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.amd.gerrit.plugins.manifestsubscription;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.VersionedMetaData;

import com.amd.gerrit.plugins.manifestsubscription.manifest.Manifest;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathSuffixFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class VersionedManifests extends VersionedMetaData implements ManifestProvider {
  private static final Logger log =
      LoggerFactory.getLogger(VersionedManifests.class);

  private String refName;
  private Unmarshaller manifestUnmarshaller;
  private Marshaller manifestMarshaller;
  private Map<String, Manifest> manifests;
  private String srcManifestRepo = "";
  private String extraCommitMsg = "";

  public String getExtraCommitMsg() {
    return extraCommitMsg;
  }

  public void setExtraCommitMsg(String extraCommitMsg) {
    this.extraCommitMsg = extraCommitMsg;
  }

  public String getSrcManifestRepo() {
    return srcManifestRepo;
  }

  public void setSrcManifestRepo(String srcManifestRepo) {
    this.srcManifestRepo = srcManifestRepo;
  }

  public Map<String, Manifest> getManifests() {
    return Collections.unmodifiableMap(manifests);
  }

  public void setManifests(Map<String, Manifest> manifests) {
    this.manifests = manifests;
  }

  public Set<String> getManifestPaths() {
    return manifests.keySet();
  }

  private VersionedManifests() throws JAXBException {
    JAXBContext jaxbctx = JAXBContext.newInstance(Manifest.class);
    this.manifestUnmarshaller = jaxbctx.createUnmarshaller();
    this.manifestMarshaller = jaxbctx.createMarshaller();
    this.manifestMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  }

  public VersionedManifests(String refName)
      throws JAXBException {
    this();
    this.refName = refName;

  }

  public VersionedManifests(String refName,
                            Map<String, Manifest> manifests) throws JAXBException {
    this(refName);
    this.manifests = manifests;

  }

  @Override
  protected String getRefName() {
    return refName;
  }

  @Override
  protected void onLoad() throws IOException, ConfigInvalidException {
    manifests = Maps.newHashMap();

    String path;
    Manifest manifest;

    try (RevWalk rw = new RevWalk(reader);
         TreeWalk treewalk = new TreeWalk(reader)) {
      // This happens when someone configured a invalid branch name
      if (getRevision() == null) {
        throw new ConfigInvalidException(refName);
      }
      RevCommit r = rw.parseCommit(getRevision());
      treewalk.addTree(r.getTree());
      treewalk.setRecursive(false);
      treewalk.setFilter(PathSuffixFilter.create(".xml"));
      while (treewalk.next()) {
        if (treewalk.isSubtree()) {
          treewalk.enterSubtree();
        } else {
          path = treewalk.getPathString();
          //TODO: Should this be done more lazily?
          //TODO: difficult to do when reader is not available outside of onLoad?
          try (ByteArrayInputStream input
                   = new ByteArrayInputStream(readFile(path))) {
            manifest = (Manifest) manifestUnmarshaller.unmarshal(input);
            manifests.put(path, manifest);
          } catch (JAXBException e) {
            e.printStackTrace();
          }
        }
      }
    }

    //TODO load changed manifest
//    DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
  }

  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException {
    // extra commit message (such as the one-liner git log) is put in
    // the body because:
    // 1) not all manifest update has a one-line git log (such as
    //    the manifest generated from the initial subscription)
    // 2) An manifest update may contain multiple project, which means
    //    multiple one-line git log
    StringBuilder commitMsg = new StringBuilder();
    commitMsg.append("Snapshot manifest from " +
        srcManifestRepo + " updated\n\n");

    if (extraCommitMsg != null && extraCommitMsg.length() > 0) {
      commitMsg.append(extraCommitMsg);
    }

    String path;
    Manifest manifest;
    for (Map.Entry<String, Manifest> entry : manifests.entrySet()) {
      path = entry.getKey();
      manifest = entry.getValue();

      try {
        saveManifest(path, manifest);
      } catch (JAXBException e) {
        throw new IOException(e);
      }
    }

    // For some reason the default author and committer date is
    // invalid (always the same date and time)
    Date date = new Date();
    commit.setAuthor(new PersonIdent(commit.getAuthor(), date));
    commit.setCommitter(new PersonIdent(commit.getCommitter(), date));

    if (commit.getMessage() == null || "".equals(commit.getMessage())) {
      commit.setMessage(commitMsg.toString());
    }

    return true;
  }

  @Override
  public Manifest readManifest(String path) throws ManifestReadException {
    if (manifests.containsKey(path)) {
      return manifests.get(path);
    }

    throw new ManifestReadException(path);
  }

  /**
   * Must be called inside onSave
   *
   * @param path
   * @param manifest
   * @throws JAXBException
   * @throws IOException
   */
  private void saveManifest(String path, Manifest manifest)
      throws JAXBException, IOException {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    manifestMarshaller.marshal(manifest, output);
    saveFile(path, output.toByteArray());
  }

  static void tagManifest(GitRepositoryManager gitRepoManager,
                             Manifest manifest,
                             final String tag)
      throws GitAPIException, IOException {
    Table<String, String, String> lookup = HashBasedTable.create();
    String defaultRef = null;

    if (manifest.getDefault() != null) {
      defaultRef = manifest.getDefault().getRevision();
    }

    ManifestOp op = new ManifestOp() {
      @Override
      public boolean apply(com.amd.gerrit.plugins.manifestsubscription.manifest.Project project,
                           String hash, String name,
                           GitRepositoryManager gitRepoManager) throws
          GitAPIException, IOException {
        Project.NameKey p = new Project.NameKey(project.getName());
        try (Repository db = gitRepoManager.openRepository(p);
             Git git = new Git(db);
             RevWalk walk = new RevWalk(db)) {
          RevCommit commit = walk.parseCommit(db.resolve(hash));
          git.tag().setName(tag).setObjectId(commit).setAnnotated(true).call();
        }
        return true;
      }
    };

    traverseManifestAndApplyOp(gitRepoManager, manifest.getProject(), defaultRef, op, lookup);
  }

  static void branchManifest(GitRepositoryManager gitRepoManager,
                             Manifest manifest,
                             final String branch,
                             final GitReferenceUpdated gitReferenceUpdated)
                                          throws GitAPIException, IOException {
    Table<String, String, String> lookup = HashBasedTable.create();
    String defaultRef = null;

    if (manifest.getDefault() != null) {
      defaultRef = manifest.getDefault().getRevision();
    }

    ManifestOp op = new ManifestOp() {
      @Override
      public boolean apply(com.amd.gerrit.plugins.manifestsubscription.manifest.Project project,
                           String hash, String name,
                           GitRepositoryManager gitRepoManager) throws
          GitAPIException, IOException {
        Project.NameKey p = new Project.NameKey(project.getName());
        try (Repository db = gitRepoManager.openRepository(p);
             Git git = new Git(db)) {
          try {
            Ref r = git.branchCreate().setName(branch).setStartPoint(hash).call();
            gitReferenceUpdated.fire(p, branch, ObjectId.zeroId(), r.getObjectId());
          } catch (Exception e) {

          }
        }
        return true;
      }
    };

    traverseManifestAndApplyOp(gitRepoManager, manifest.getProject(), defaultRef, op, lookup);
  }

  /**
   * Pass in a {@link com.google.common.collect.Table} if you want to reuse
   * the lookup cache
   *
   * @param gitRepoManager
   * @param manifest
   * @param lookup
   */
  static void affixManifest(GitRepositoryManager gitRepoManager,
                            Manifest manifest,
                            Table<String, String, String> lookup)
                                          throws GitAPIException, IOException {
    if (lookup == null) {
      // project, branch, hash
      lookup = HashBasedTable.create();
    }

    String defaultRef = null;

    if (manifest.getDefault() != null) {
      defaultRef = manifest.getDefault().getRevision();
    }

    ManifestOp op = new ManifestOp() {
      @Override
      public boolean apply(com.amd.gerrit.plugins.manifestsubscription.manifest.Project project,
                           String hash, String name,
                           GitRepositoryManager gitRepoManager) {
        project.setRevision(hash);
        if (!ObjectId.isId(name)) {
          project.setUpstream(name);
        }
        return true;
      }
    };

    traverseManifestAndApplyOp(gitRepoManager, manifest.getProject(), defaultRef, op, lookup);
  }

  static void traverseManifestAndApplyOp(
      GitRepositoryManager gitRepoManager,
      List<com.amd.gerrit.plugins.manifestsubscription.manifest.Project> projects,
      String defaultRef,
      ManifestOp op,
      Table<String, String, String> lookup) throws GitAPIException, IOException {

    String ref;
    String hash;
    String projectName;
    Project.NameKey p;
    for (com.amd.gerrit.plugins.manifestsubscription.manifest.Project project : projects) {
      projectName = project.getName();
      ref = project.getRevision();

      ref = (ref == null) ? defaultRef : ref;

      if (ref != null) {
        if (lookup != null) {
          hash = lookup.get(projectName, ref);
        } else {
          hash = null;
        }

        if (hash == null) {
          p = new Project.NameKey(projectName);
          try (Repository db = gitRepoManager.openRepository(p)) {
            hash = db.resolve(ref).getName();
          } catch (IOException | NullPointerException e) {
            log.warn("Cannot resolve ref: " + ref +
                "\n\t" + projectName +
                "\n\t" + defaultRef +
                "\n\t" + Arrays.toString(e.getStackTrace()));
          }
        }

        if (hash != null) {
          if (lookup != null) lookup.put(projectName, ref, hash);
          op.apply(project, hash, ref, gitRepoManager);
        }
      }

      if (project.getProject().size() > 0) {
        traverseManifestAndApplyOp(gitRepoManager, project.getProject(), defaultRef, op, lookup);
      }
    }
  }
}
