// 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.amd.gerrit.plugins.manifestsubscription.manifest.Manifest;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.VersionedMetaData;
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.PersonIdent;
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 javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

public class VersionedManifests extends VersionedMetaData implements ManifestProvider {
  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;

    RevWalk rw = new RevWalk(reader);

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

    treewalk.release();

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

  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException {
    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());
        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();

        git.close();
        return true;
      }
    };

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

  static void branchManifest(GitRepositoryManager gitRepoManager,
                             Manifest manifest,
                             final String branch)
                                          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());
        Repository db = gitRepoManager.openRepository(p);
        Git git = new Git(db);

        git.branchCreate().setName(branch).setStartPoint(hash).call();

        git.close();
        //db.close(); //closed by git.close()
        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);
        project.setUpstream(name);
        return true;
      }
    };

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

  private 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) {
        hash = lookup.get(projectName, ref);

        if (hash == null) {
          p = new Project.NameKey(projectName);
          try {
            Repository db = gitRepoManager.openRepository(p);

            hash = db.resolve(ref).getName();
            db.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }

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

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