// 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.autoreindex;

import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.AbstractIndexRestApiServlet;
import com.google.common.base.Stopwatch;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

abstract class ReindexRunnable<T> implements Runnable {
  private static final Logger log = LoggerFactory.getLogger(ReindexRunnable.class);

  private final AbstractIndexRestApiServlet.IndexName itemName;
  private final OneOffRequestContext ctx;
  private final IndexTs indexTs;

  @Inject
  public ReindexRunnable(
      AbstractIndexRestApiServlet.IndexName itemName, IndexTs indexTs, OneOffRequestContext ctx) {
    this.itemName = itemName;
    this.ctx = ctx;
    this.indexTs = indexTs;
  }

  @Override
  public void run() {
    Optional<LocalDateTime> maybeIndexTs = indexTs.getUpdateTs(itemName);
    String itemNameString = itemName.name().toLowerCase();
    if (maybeIndexTs.isPresent()) {
      Timestamp lastIndexTs = Timestamp.valueOf(maybeIndexTs.get());
      Timestamp newLastIndexTs = lastIndexTs;
      log.debug("Scanning for all the {}s after {}", itemNameString, lastIndexTs);
      try (ManualRequestContext mctx = ctx.open();
          ReviewDb db = mctx.getReviewDbProvider().get()) {
        int count = 0;
        int errors = 0;
        Stopwatch stopwatch = Stopwatch.createStarted();
        for (T c : fetchItems(db)) {
          try {
            Optional<Timestamp> itemTs = indexIfNeeded(db, c, lastIndexTs);
            if (itemTs.isPresent()) {
              count++;
              if (itemTs.get().after(newLastIndexTs)) {
                newLastIndexTs = itemTs.get();
              }
            }
          } catch (Exception e) {
            log.error("Unable to reindex {} {}", itemNameString, c, e);
            errors++;
          }
        }
        long elapsedNanos = stopwatch.stop().elapsed(TimeUnit.NANOSECONDS);
        if (count > 0) {
          log.info(
              "{} {}s reindexed in {} msec ({}/sec), {} failed",
              count,
              itemNameString,
              elapsedNanos / 1000000L,
              (count * 1000L) / (elapsedNanos / 1000000L),
              errors);
        } else if (errors > 0) {
          log.info("{} {}s failed to reindex", errors, itemNameString);
        } else {
          log.debug("Scanning finished");
        }
        indexTs.update(itemName, newLastIndexTs.toLocalDateTime());
      } catch (Exception e) {
        log.error("Unable to scan " + itemNameString + "s", e);
      }
    }
  }

  protected abstract Iterable<T> fetchItems(ReviewDb db) throws Exception;

  protected abstract Optional<Timestamp> indexIfNeeded(ReviewDb db, T item, Timestamp sinceTs);
}
