// Copyright (C) 2018 The Android Open Source Project
//
// 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.ericsson.gerrit.plugins.highavailability.index;

import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Optional;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

public class ChangeCheckerImpl implements ChangeChecker {
  private static final FluentLogger log = FluentLogger.forEnclosingClass();
  private final GitRepositoryManager gitRepoMgr;
  private final CommentsUtil commentsUtil;
  private final OneOffRequestContext oneOffReqCtx;
  private final String changeId;
  private final ChangeFinder changeFinder;
  private Optional<Long> computedChangeTs = Optional.empty();
  private Optional<ChangeNotes> changeNotes = Optional.empty();

  public interface Factory {
    ChangeChecker create(String changeId);
  }

  @Inject
  public ChangeCheckerImpl(
      GitRepositoryManager gitRepoMgr,
      CommentsUtil commentsUtil,
      ChangeFinder changeFinder,
      OneOffRequestContext oneOffReqCtx,
      @Assisted String changeId) {
    this.changeFinder = changeFinder;
    this.gitRepoMgr = gitRepoMgr;
    this.commentsUtil = commentsUtil;
    this.oneOffReqCtx = oneOffReqCtx;
    this.changeId = changeId;
  }

  @Override
  public Optional<IndexEvent> newIndexEvent() throws IOException {
    Optional<Long> changeTs = getComputedChangeTs();
    if (!changeTs.isPresent()) {
      return Optional.empty();
    }

    long ts = changeTs.get();

    IndexEvent event = new IndexEvent();
    event.eventCreatedOn = ts;
    try (Repository repo = gitRepoMgr.openRepository(changeNotes.get().getProjectName())) {
      event.targetSha = getBranchTargetSha(repo);
      event.metaSha = getMetaSha(repo);
      return Optional.of(event);
    } catch (IOException e) {
      log.atSevere().withCause(e).log(
          "Unable to create index event for project %s", changeNotes.get().getProjectName());
      throw e;
    }
  }

  @Override
  public Optional<ChangeNotes> getChangeNotes() {
    try (ManualRequestContext ctx = oneOffReqCtx.open()) {
      changeNotes = Optional.ofNullable(changeFinder.findOne(changeId));
      return changeNotes;
    }
  }

  @Override
  public boolean isChangeUpToDate(Optional<IndexEvent> indexEventOption) throws IOException {
    getComputedChangeTs();
    log.atFine().log("Checking change %s against index event %s", this, indexEventOption);
    if (!computedChangeTs.isPresent()) {
      log.atWarning().log("Unable to compute last updated ts for change %s", changeId);
      return false;
    }
    try {
      if (indexEventOption.isPresent()) {
        try (Repository repo = gitRepoMgr.openRepository(changeNotes.get().getProjectName())) {
          IndexEvent indexEvent = indexEventOption.get();
          return (computedChangeTs.get() > indexEvent.eventCreatedOn)
              || (computedChangeTs.get() == indexEvent.eventCreatedOn)
                  && (Objects.isNull(indexEvent.targetSha)
                      || Objects.equals(getBranchTargetSha(repo), indexEvent.targetSha))
                  && (Objects.isNull(indexEvent.metaSha)
                      || Objects.equals(getMetaSha(repo), indexEvent.metaSha));
        }
      }
      return true;

    } catch (IOException ex) {
      log.atWarning().log("Unable to read meta sha for change %s", changeId);
      return false;
    }
  }

  @Override
  public Optional<Long> getComputedChangeTs() {
    if (!computedChangeTs.isPresent()) {
      computedChangeTs = computeLastChangeTs();
    }
    return computedChangeTs;
  }

  @Override
  public String toString() {
    try (Repository repo = gitRepoMgr.openRepository(changeNotes.get().getProjectName())) {
      return "change-id="
          + changeId
          + "@"
          + getComputedChangeTs().map(IndexEvent::format)
          + "/target:"
          + getBranchTargetSha(repo)
          + "/meta:"
          + getMetaSha(repo);
    } catch (IOException e) {
      log.atSevere().withCause(e).log("Unable to render change %s", changeId);
      return "change-id=" + changeId;
    }
  }

  private String getBranchTargetSha(Repository repo) {
    try {
      String refName = changeNotes.get().getChange().getDest().get();
      Ref ref = repo.exactRef(refName);
      if (ref == null) {
        log.atWarning().log("Unable to find target ref %s for change %s", refName, changeId);
        return null;
      }
      return ref.getTarget().getObjectId().getName();
    } catch (IOException e) {
      log.atWarning().withCause(e).log(
          "Unable to resolve target branch SHA for change %s", changeId);
      return null;
    }
  }

  private Optional<Long> computeLastChangeTs() {
    return getChangeNotes().map(this::getTsFromChangeAndDraftComments);
  }

  private String getMetaSha(Repository repo) throws IOException {
    String refName = RefNames.changeMetaRef(changeNotes.get().getChange().getId());
    Ref ref = repo.exactRef(refName);
    if (ref == null) {
      throw new IOException(
          String.format("Unable to find meta ref %s for change %s", refName, changeId));
    }
    return ref.getTarget().getObjectId().getName();
  }

  private long getTsFromChangeAndDraftComments(ChangeNotes notes) {
    Change change = notes.getChange();
    Timestamp changeTs = change.getLastUpdatedOn();
    for (Comment comment : commentsUtil.draftByChange(changeNotes.get())) {
      Timestamp commentTs = comment.writtenOn;
      changeTs = commentTs.after(changeTs) ? commentTs : changeTs;
    }
    return changeTs.getTime() / 1000;
  }
}
