// Copyright (C) 2017 Google Inc
//
// 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.googlesource.gerrit.plugins.supermanifest;

import static com.google.gerrit.reviewdb.client.RefNames.REFS_HEADS;

import com.google.gerrit.reviewdb.client.Project;
import com.googlesource.gerrit.plugins.supermanifest.SuperManifestRefUpdatedListener.GerritRemoteReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Repository;

class JiriManifestParser {
  static class ManifestItem {
    public ManifestItem(
        String repoKey, String manifest, String ref, String pKey, boolean revisionPinned) {
      this.repoKey = repoKey;
      this.manifest = manifest;
      this.ref = ref;
      this.revisionPinned = revisionPinned;
      this.projectKey = pKey;
    }

    String repoKey;
    String manifest;
    String ref;
    boolean revisionPinned;

    // In jiri if import is pinned to a revision and if
    // we have a corresponding project in the manifest, jiri would
    // pin that project to same revision. So passing key to match
    // project to import tag.
    //  For Eg, if you have manifest in manifest2 repo
    //          <manifest><projects><project name="manifest2" .../>
    //  And If you import this from your main manifest
    //          <manifest><imports><import name="manifest2" revision="A"... />
    //  jiri will pin manifest2 project to A as well.
    String projectKey;
  }

  static class RepoMap<K, V extends Repository> extends HashMap<K, V> implements AutoCloseable {
    @Override
    public void close() {
      for (Repository repo : this.values()) {
        repo.close();
      }
    }
  }

  public static JiriProjects getProjects(
      GerritRemoteReader reader, String repoKey, String ref, String manifest)
      throws ConfigInvalidException, IOException {

    try (RepoMap<String, Repository> repoMap = new RepoMap<>()) {
      repoMap.put(repoKey, reader.openRepository(repoKey));
      Queue<ManifestItem> q = new LinkedList<>();
      q.add(new ManifestItem(repoKey, manifest, ref, "", false));
      HashMap<String, HashSet<String>> processedRepoFiles = new HashMap<>();
      HashMap<String, JiriProjects.Project> projectMap = new HashMap<>();

      while (q.size() != 0) {
        ManifestItem mi = q.remove();
        Repository repo = repoMap.get(mi.repoKey);
        if (repo == null) {
          repo = reader.openRepository(mi.repoKey);
          repoMap.put(mi.repoKey, repo);
        }
        HashSet<String> processedFiles = processedRepoFiles.get(mi.repoKey);
        if (processedFiles == null) {
          processedFiles = new HashSet<String>();
          processedRepoFiles.put(mi.repoKey, processedFiles);
        }
        if (processedFiles.contains(mi.manifest)) {
          continue;
        }
        processedFiles.add(mi.manifest);
        JiriManifest m;
        try {
          m = parseManifest(repo, mi.ref, mi.manifest);
        } catch (JAXBException | XMLStreamException e) {
          throw new ConfigInvalidException("XML parse error", e);
        }

        for (JiriProjects.Project project : m.projects.getProjects()) {
          project.fillDefault();
          if (mi.revisionPinned && project.Key().equals(mi.projectKey)) {
            project.setRevision(mi.ref);
          }
          if (projectMap.containsKey(project.Key())) {
            if (!projectMap.get(project.Key()).equals(project))
              throw new ConfigInvalidException(
                  String.format(
                      "Duplicate conflicting project %s in manifest %s\n%s\n%s",
                      project.Key(),
                      mi.manifest,
                      project.toString(),
                      projectMap.get(project.Key()).toString()));
          } else {
            projectMap.put(project.Key(), project);
          }
        }

        URI parentURI;
        try {
          parentURI = new URI(mi.manifest);
        } catch (URISyntaxException e) {
          throw new ConfigInvalidException("Invalid parent URI", e);
        }
        for (JiriManifest.LocalImport l : m.imports.getLocalImports()) {
          ManifestItem tw =
              new ManifestItem(
                  mi.repoKey,
                  parentURI.resolve(l.getFile()).getPath(),
                  mi.ref,
                  mi.projectKey,
                  mi.revisionPinned);
          q.add(tw);
        }

        for (JiriManifest.Import i : m.imports.getImports()) {
          i.fillDefault();
          URI uri;
          try {
            uri = new URI(i.getRemote());
          } catch (URISyntaxException e) {
            throw new ConfigInvalidException("Invalid URI", e);
          }
          String iRepoKey = new Project.NameKey(StringUtils.strip(uri.getPath(), "/")).toString();
          String iRef = i.getRevision();
          boolean revisionPinned = true;
          if (iRef.isEmpty()) {
            iRef = REFS_HEADS + i.getRemotebranch();
            revisionPinned = false;
          }

          ManifestItem tmi =
              new ManifestItem(iRepoKey, i.getManifest(), iRef, i.Key(), revisionPinned);
          q.add(tmi);
        }
      }
      return new JiriProjects(projectMap.values().toArray(new JiriProjects.Project[0]));
    }
  }

  private static JiriManifest parseManifest(Repository repo, String ref, String file)
      throws JAXBException, IOException, XMLStreamException {
    byte[] b = Utils.readBlob(repo, ref + ":" + file);
    JAXBContext jc = JAXBContext.newInstance(JiriManifest.class);

    XMLInputFactory inf = XMLInputFactory.newFactory();
    inf.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
    inf.setProperty(XMLInputFactory.SUPPORT_DTD, false);
    XMLStreamReader sr = inf.createXMLStreamReader(new StreamSource(new ByteArrayInputStream(b)));

    return (JiriManifest) jc.createUnmarshaller().unmarshal(sr);
  }
}
