// 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 static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;

import com.amd.gerrit.plugins.manifestsubscription.manifest.Manifest;
import com.google.common.collect.*;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.util.*;

public class ManifestSubscription implements
    GitReferenceUpdatedListener, LifecycleListener {
  private static final Logger log =
      LoggerFactory.getLogger(ManifestSubscription.class);

  private static final String KEY_BRANCH = "branch";
  private static final String KEY_STORE = "store";

  static final String STORE_BRANCH_PREFIX = "refs/heads/m/";

  private final String pluginName;

  private final MetaDataUpdate.Server metaDataUpdateFactory;
  private final GitRepositoryManager gitRepoManager;
  private final ProjectCache projectCache;
  private final ChangeHooks changeHooks;


  /**
   * source project lookup
   * manifest source project name, plugin config
   **/
  private Map<String, PluginProjectConfig> enabledManifestSource = Maps.newHashMap();

  /**
   * manifest store lookup
   * repo name, branch (branchPath), Manifest
   */
  private Table<String, String, Manifest> manifestStores = HashBasedTable.create();

  /**
   * manifest source lookup
   * repo name, branch (branchPath), manifest source repo
   */
  private Table<String, String, String> manifestSource = HashBasedTable.create();

  /**
   * lookup
   * subscribed project name and branch, manifest dest store, <manifest dest branch Project>
   **/
  private Table<ProjectBranchKey, String, Map<String, Set<
      com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>> subscribedRepos = HashBasedTable.create();

  public Set<String> getEnabledManifestSource() {
    return ImmutableSet.copyOf(enabledManifestSource.keySet());
  }

  public Set<ProjectBranchKey> getSubscribedProjects() {
    return ImmutableSet.copyOf(subscribedRepos.rowKeySet());
  }

  public ImmutableTable<ProjectBranchKey, String, Map<String, Set<
      com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>> getSubscribedRepos() {
    return new ImmutableTable.Builder<ProjectBranchKey, String, Map<String, Set<
      com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>>().putAll(subscribedRepos).build();
  }

  @Override
  public void start() {
    ProjectConfig config;
    for (Project.NameKey p : projectCache.all()) {
      //TODO parallelize parsing/load up?
      try {
        config = ProjectConfig.read(metaDataUpdateFactory.create(p));
        loadStoreFromProjectConfig(p.toString(), config);

      } catch (IOException | ConfigInvalidException | JAXBException e) {
        log.error(e.toString());
        e.printStackTrace();
      }
    }
  }

  @Override
  public void stop() {

  }

  @Inject
  ManifestSubscription(MetaDataUpdate.Server metaDataUpdateFactory,
                       GitRepositoryManager gitRepoManager,
                       @PluginName String pluginName,
                       ProjectCache projectCache,
                       ChangeHooks changeHooks) {
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.gitRepoManager = gitRepoManager;
    this.pluginName = pluginName;
    this.projectCache = projectCache;
    this.changeHooks = changeHooks;
  }

  @Override
  public void onGitReferenceUpdated(Event event) {
    String projectName = event.getProjectName();
    String refName = event.getRefName();
    String branchName = refName.startsWith("refs/heads/") ?
        refName.substring(11) : refName;
    ProjectBranchKey pbKey = new ProjectBranchKey(projectName, branchName);

    if (event.getNewObjectId().equals(ObjectId.zeroId().toString())) {
      // This happens when there's a branch deletion and possibly other events
      log.info("Project: " + projectName +
               "\nrefName: " + refName);
    } else if (REFS_CONFIG.equals(refName)) {
      // possible change in enabled repos
      processProjectConfigChange(event);
    } else if (enabledManifestSource.containsKey(projectName) &&
        enabledManifestSource.get(projectName)
            .getBranches().contains(branchName)) {
      processManifestChange(event, projectName, branchName);

    } else if (subscribedRepos.containsRow(pbKey)) {
      //updates in subscribed repos
      processRepoChange(event.getNewObjectId(), projectName, pbKey);
    }
  }

  void processRepoChange(String refUpdatedHash, String projectName,
                                 ProjectBranchKey pbKey) {
    // Manifest store and branch
    Map<String, Map<String, Set<
            com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>>
        destinations = subscribedRepos.row(pbKey);

    for (String store : destinations.keySet()) {
      for (String storeBranch : destinations.get(store).keySet()) {
        Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project> ps
            = destinations.get(store).get(storeBranch);

        Manifest manifest = manifestStores.get(store, storeBranch);
        String manifestSrc = manifestSource.get(store, storeBranch);
        StringBuilder extraCommitMsg = new StringBuilder();

        Project.NameKey p = new Project.NameKey(projectName);
        try (Repository r = gitRepoManager.openRepository(p);
             RevWalk walk = new RevWalk(r)) {

          RevCommit c = walk.parseCommit(
              ObjectId.fromString(refUpdatedHash));

          extraCommitMsg.append(refUpdatedHash.substring(0,7));
          extraCommitMsg.append(" ");
          extraCommitMsg.append(projectName);
          extraCommitMsg.append(" ");
          extraCommitMsg.append(c.getShortMessage());
        } catch (IOException e) {
          e.printStackTrace();
        }

        // these are project from the above manifest previously
        // cached in the lookup table
        for (com.amd.gerrit.plugins.manifestsubscription.manifest.Project
            updateProject : ps) {
          updateProject.setRevision(refUpdatedHash);
        }

        try {
          Utilities.updateManifest(gitRepoManager, metaDataUpdateFactory,
              changeHooks, store, STORE_BRANCH_PREFIX + storeBranch,
              manifest, manifestSrc, extraCommitMsg.toString(), null);
        } catch (JAXBException | IOException e) {
          e.printStackTrace();
        }

      }
    }
  }

  private void updateProjectRev(String projectName, String branch, String rev,
                                List<com.amd.gerrit.plugins.
                                    manifestsubscription.manifest.Project> projects) {
    //TODO optimize to not have to iterate through manifest?
    for (com.amd.gerrit.plugins.manifestsubscription.manifest.Project project : projects) {
      if (Objects.equals(projectName, project.getName()) &&
          Objects.equals(branch, project.getUpstream())) {
        project.setRevision(rev);
      }

      if (project.getProject().size() > 0) {
        updateProjectRev(projectName, branch, rev, project.getProject());
      }
    }

  }

  private void processManifestChange(Event event,
                                     String projectName, String branchName) {
    try {
      VersionedManifests versionedManifests = parseManifests(event);
      processManifestChange(versionedManifests, projectName, branchName);
    } catch (JAXBException | IOException | ConfigInvalidException e) {
      e.printStackTrace();
    }

  }

  private void processManifestChange(VersionedManifests versionedManifests,
                                     String projectName, String branchName) {
    //possible manifest update in subscribing repos
    //TODO Fix, right now update all manifest every time
    //TODO even when only one of the manifest has changed

    try {
      if (versionedManifests != null) {
        CanonicalManifest cManifest = new CanonicalManifest(versionedManifests);
        Set<String> manifests = versionedManifests.getManifestPaths();
        Manifest manifest;
        String store = enabledManifestSource.get(projectName).getStore();
        Table<String, String, String> lookup = HashBasedTable.create();

        // Remove old manifest from subscription if destination store and branch
        // matches manifest source being updated
        // TODO again, this assume 1-1 map between store and manifest store
        Map<String,
            Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project>> branchPaths;
        for (Table.Cell<ProjectBranchKey, String,
            Map<String,
                Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>> cell :
            subscribedRepos.cellSet()) {
          if (store.equals(cell.getColumnKey())) {
            branchPaths = cell.getValue();

            Iterator<String> iter = branchPaths.keySet().iterator();
            String branchPath;
            while (iter.hasNext()) {
              branchPath = iter.next();
              if (branchPath.startsWith(branchName+"/")) {
                iter.remove();
                manifestStores.remove(store, branchPath);
                manifestSource.remove(store, branchPath);
              }
            }
          }
        }

        //TODO need to make sure remote is pointing to this server?
        //TODO this may be impossible
        //TODO only monitor projects without 'remote' attribute / only using default?

        for (String path : manifests) {
          String bp = branchName + "/" + path;
          try {
            manifest = cManifest.getCanonicalManifest(path);

            watchCanonicalManifest(manifest, store, bp, projectName);

            VersionedManifests.affixManifest(gitRepoManager, manifest, lookup);
            //save manifest
            //TODO added the m/ to the ref to to work around LOCK_FAILURE error of creating master/bla/bla
            //TODO (because default master ref already exists) better solution?
            updateManifest(store, STORE_BRANCH_PREFIX + bp,
                           manifest, projectName);

          } catch (ManifestReadException | GitAPIException e) {
            e.printStackTrace();
          }

        }

      }
    } catch (JAXBException | IOException e) {
      e.printStackTrace();
    }

  }

  private void watchCanonicalManifest(Manifest manifest, String store,
                                      String branchPath, String manifestSrc) {
    String defaultBranch;
    if (manifest.getDefault() != null &&
        manifest.getDefault().getRevision() != null) {
      defaultBranch = manifest.getDefault().getRevision();
    } else {
      defaultBranch = "";
    }

    manifestStores.put(store, branchPath, manifest);
    manifestSource.put(store, branchPath, manifestSrc);

    List<com.amd.gerrit.plugins.manifestsubscription.manifest.Project> projects
        = manifest.getProject();
    watchProjectsInCanonicalManifest(store, branchPath, defaultBranch, projects);
  }

  private void watchProjectsInCanonicalManifest(String store, String branchPath,
                                                String defaultBranch,
                                                List<com.amd.gerrit.plugins.manifestsubscription.manifest.Project> projects) {
    ProjectBranchKey pbKey;
    for (com.amd.gerrit.plugins.manifestsubscription.manifest.Project project : projects) {
      if (manifestStores.containsRow(project.getName()) &&
          !manifestStores.row(project.getName()).isEmpty()) {
        // Skip if it's one of the repo for storing
        // manifest to avoid infinite loop
        // This is a bit too general, but it's done to avoid the complexity
        // of actually tracing out the loop
        // i.e. manifest1->store2 --> manifest2->store1
        continue;
      }

      String branch = project.getRevision() == null ?
          defaultBranch : project.getRevision();
      pbKey = new ProjectBranchKey(project.getName(),
          Repository.shortenRefName(branch));


      //TODO only update manifests that changed
      if (!subscribedRepos.contains(pbKey, store)) {
        subscribedRepos.put(pbKey, store,
            Maps.<String, Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>newHashMap());
      }

      Map<String,
          Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project>> ps;
      ps = subscribedRepos.get(pbKey, store);
      if (!ps.containsKey(branchPath)) {
        ps.put(branchPath,
            Sets.<com.amd.gerrit.plugins.manifestsubscription.manifest.Project>newHashSet());
      }
      ps.get(branchPath).add(project);

      if (project.getProject().size() > 0) {
        watchProjectsInCanonicalManifest(store, branchPath, defaultBranch,
            project.getProject());
      }
    }
  }

  private void processProjectConfigChange(Event event) {
    Project.NameKey p = new Project.NameKey(event.getProjectName());

    //TODO test two separate project configured to the same store
    try {
      ProjectConfig oldCfg = parseConfig(p, event.getOldObjectId());
      ProjectConfig newCfg = parseConfig(p, event.getNewObjectId());

      //TODO selectively update changes instead of complete reset
      if (oldCfg != null) {
        String oldStore =
            oldCfg.getPluginConfig(pluginName).getString(KEY_STORE);

        if (oldStore != null && !oldStore.isEmpty()) {
          //TODO FIX assume unique store for each manifest source (1-1 map)
          manifestStores.row(oldStore).clear();
          manifestSource.row(oldStore).clear();
          enabledManifestSource.remove(event.getProjectName());

          Iterator<Table.Cell<ProjectBranchKey, String, Map<String,
              Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>>> iter =
              subscribedRepos.cellSet().iterator();
          while (iter.hasNext()) {
            if (oldStore.equals(iter.next().getColumnKey())) {
              iter.remove();
            }
          }
        }
      }

      if (newCfg != null) {
        loadStoreFromProjectConfig(event.getProjectName(), newCfg);

      }
    } catch (IOException | ConfigInvalidException | JAXBException e) {
      e.printStackTrace();
    }
  }

  private void loadStoreFromProjectConfig(String projectName,
                                          ProjectConfig config)
      throws JAXBException, IOException, ConfigInvalidException {
    String newStore =
        config.getPluginConfig(pluginName).getString(KEY_STORE);

    if (newStore != null) {
      newStore = newStore.trim();
      if (!newStore.isEmpty()) {
        Set<String> branches = Sets.newHashSet(
            config.getPluginConfig(pluginName)
                .getStringList(KEY_BRANCH));

        if (branches.size() > 0) {
          PluginProjectConfig ppc = new PluginProjectConfig(newStore, branches);

          enabledManifestSource.put(projectName, ppc);
          Project.NameKey nameKey = new Project.NameKey(projectName);
          VersionedManifests versionedManifests;
          for (String branch : branches) {
            versionedManifests = parseManifests(nameKey, branch);
            processManifestChange(versionedManifests, projectName, branch);
          }
        }
      }
    }
  }

  private ProjectConfig parseConfig(Project.NameKey p, String idStr)
      throws IOException, ConfigInvalidException {
    ObjectId id = ObjectId.fromString(idStr);
    if (ObjectId.zeroId().equals(id)) {
      return null;
    }
    return ProjectConfig.read(metaDataUpdateFactory.create(p), id);
  }

  private VersionedManifests parseManifests(Event event)
      throws JAXBException, IOException, ConfigInvalidException {
    Project.NameKey p = new Project.NameKey(event.getProjectName());
    return parseManifests(p, event.getRefName());
  }

  private VersionedManifests parseManifests(Project.NameKey p, String refName)
      throws IOException, JAXBException, ConfigInvalidException {

    Repository repo = gitRepoManager.openRepository(p);
    ObjectId commitId = repo.resolve(refName);
    MetaDataUpdate update = metaDataUpdateFactory.create(p);
    VersionedManifests vManifests = new VersionedManifests(refName);
    vManifests.load(update, commitId);

    return vManifests;
  }

  private void updateManifest(String projectName, String refName,
                              Manifest manifest, String manifestSrc)
      throws JAXBException, IOException {
    Utilities.updateManifest(gitRepoManager, metaDataUpdateFactory, changeHooks,
        projectName, refName, manifest, manifestSrc, "", null);
  }

}
