// 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.entities.RefNames.REFS_HEADS;

import com.google.gerrit.entities.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 {
    private static final long serialVersionUID = 1L;

    @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<>();
          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 = 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);
  }
}
