// 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.*;
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.Branch;
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";

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

  @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) : "";
    ProjectBranchKey pbKey = new ProjectBranchKey(projectName, branchName);

    if ("refs/meta/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

      // 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();

          try {
            Project.NameKey p = new Project.NameKey(projectName);
            Repository r = gitRepoManager.openRepository(p);
            RevWalk walk = new RevWalk(r);
            RevCommit c = walk.parseCommit(
                ObjectId.fromString(event.getNewObjectId()));

            extraCommitMsg.append(event.getNewObjectId().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(event.getNewObjectId());
          }

          try {
            updateManifest(store, STORE_BRANCH_PREFIX + storeBranch,
                           manifest, manifestSrc, extraCommitMsg.toString());
          } 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);

            VersionedManifests.affixManifest(gitRepoManager, manifest, lookup);

            watchCanonicalManifest(manifest, store, bp, projectName);
            //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;
      }

      // Make sure revision is branch ref w/o refs/heads
      String branch = project.getRevision() == null ?
          defaultBranch : (project.getUpstream() != null ?
          project.getUpstream() : 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 {

    MetaDataUpdate update = metaDataUpdateFactory.create(p);
    VersionedManifests vManifests = new VersionedManifests(refName);
    vManifests.load(update);

    return vManifests;
  }

  private void updateManifest(String projectName, String refName,
                              Manifest manifest, String manifestSrc)
      throws JAXBException, IOException {
    updateManifest(projectName, refName, manifest, manifestSrc, "");
  }

  private void updateManifest(String projectName, String refName,
                              Manifest manifest, String manifestSrc,
                              String extraCommitMsg)
      throws JAXBException, IOException {
    Project.NameKey p = new Project.NameKey(projectName);
    MetaDataUpdate update = metaDataUpdateFactory.create(p);
    VersionedManifests vManifests = new VersionedManifests(refName);

    //TODO find a better way to detect no branch
    boolean refExists = true;
    try {
      vManifests.load(update);
    } catch (Exception e) {
      refExists = false;
    }


    RevCommit commit = null;
    if (refExists) {
      Map<String, Manifest> entry = Maps.newHashMapWithExpectedSize(1);
      entry.put("default.xml", manifest);
      vManifests.setManifests(entry);
      vManifests.setSrcManifestRepo(manifestSrc);
      vManifests.setExtraCommitMsg(extraCommitMsg);
      commit = vManifests.commit(update);
    } else {
      vManifests = new VersionedManifests("master");
      try {
        vManifests.load(update);
      } catch (ConfigInvalidException e) {
        e.printStackTrace();
      }
      Map<String, Manifest> entry = Maps.newHashMapWithExpectedSize(1);
      entry.put("default.xml", manifest);
      vManifests.setManifests(entry);
      commit = vManifests.commitToNewRef(update, refName);
    }

    // TODO this may be bug in the MetaDataUpdate or VersionedMetaData
    // May be related:
    // https://code.google.com/p/gerrit/issues/detail?id=2564
    // https://gerrit-review.googlesource.com/55540
    if (commit != null) {
      changeHooks.doRefUpdatedHook(new Branch.NameKey(p, refName),
                                    commit.getParent(0).getId(),
                                    commit.getId(), null);
    } else {
      log.warn("Failing to commit manifest subscription update");
    }

  }

}
