// 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.googlesource.gerrit.plugins.replication;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.flogger.FluentLogger;
import com.google.common.hash.Hashing;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.lib.ObjectId;

@Singleton
public class EventsStorage {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static class ReplicateRefUpdate {
    public String project;
    public String ref;
  }

  private static Gson GSON = new Gson();

  private final Path refUpdates;

  @Inject
  EventsStorage(ReplicationConfig config) {
    refUpdates = config.getEventsDirectory().resolve("ref-updates");
  }

  public String persist(String project, String ref) {
    ReplicateRefUpdate r = new ReplicateRefUpdate();
    r.project = project;
    r.ref = ref;

    String json = GSON.toJson(r) + "\n";
    String eventKey = sha1(json).name();
    Path file = refUpdates().resolve(eventKey);

    if (Files.exists(file)) {
      return eventKey;
    }

    try {
      Files.write(file, json.getBytes(UTF_8));
    } catch (IOException e) {
      logger.atWarning().log("Couldn't persist event %s", json);
    }
    return eventKey;
  }

  public void delete(String eventKey) {
    if (eventKey != null) {
      try {
        Files.delete(refUpdates().resolve(eventKey));
      } catch (IOException e) {
        logger.atSevere().log("Error while deleting event %s", eventKey);
      }
    }
  }

  public List<ReplicateRefUpdate> list() {
    ArrayList<ReplicateRefUpdate> result = new ArrayList<>();
    try (DirectoryStream<Path> events = Files.newDirectoryStream(refUpdates())) {
      for (Path e : events) {
        if (Files.isRegularFile(e)) {
          String json = new String(Files.readAllBytes(e), UTF_8);
          result.add(GSON.fromJson(json, ReplicateRefUpdate.class));
          Files.delete(e);
        }
      }
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("Error when firing pending events");
    }
    return result;
  }

  @SuppressWarnings("deprecation")
  private ObjectId sha1(String s) {
    return ObjectId.fromRaw(Hashing.sha1().hashString(s, UTF_8).asBytes());
  }

  private Path refUpdates() {
    try {
      return Files.createDirectories(refUpdates);
    } catch (IOException e) {
      throw new ProvisionException(String.format("Couldn't create %s", refUpdates), e);
    }
  }
}
