// 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.Project;
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.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 {
    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)
                                          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)) {
          git.branchCreate().setName(branch).setStartPoint(hash).call();
        }
        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);
      }
    }
  }
}
