// Copyright (C) 2017 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.lfs.locks;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.lfs.LfsDateTime;
import com.googlesource.gerrit.plugins.lfs.LfsGson;
import com.googlesource.gerrit.plugins.lfs.locks.LfsLocksHandler.LfsLockExistsException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.lfs.errors.LfsException;

class LfsProjectLocks {
  interface Factory {
    LfsProjectLocks create(Project.NameKey project);
  }

  private static final FluentLogger log = FluentLogger.forEnclosingClass();
  private final LfsGson gson;
  private final String project;
  private final Path locksPath;
  private final Cache<String, LfsLock> locks;

  @Inject
  LfsProjectLocks(LfsGson gson, LfsLocksPathProvider locksPath, @Assisted Project.NameKey project) {
    this.gson = gson;
    this.project = project.get();
    this.locksPath = Paths.get(locksPath.get(), this.project);
    this.locks = CacheBuilder.newBuilder().build();
  }

  void load() {
    if (!Files.exists(locksPath)) {
      return;
    }
    try (Stream<Path> stream = Files.list(locksPath)) {
      stream
          .filter(Files::isRegularFile)
          .forEach(
              path -> {
                if (!Files.isReadable(path)) {
                  log.atWarning().log(
                      "Lock file [%s] in project %s is not readable", path, project);
                  return;
                }

                try (Reader in = Files.newBufferedReader(path)) {
                  LfsLock lock = gson.fromJson(in, LfsLock.class);
                  locks.put(lock.id, lock);
                } catch (IOException e) {
                  log.atWarning().withCause(e).log("Reading lock [%s] failed", path);
                }
              });
    } catch (IOException e) {
      log.atWarning().withCause(e).log("Reading locks in project %s failed", project);
    }
  }

  Optional<LfsLock> getLock(String lockId) {
    return Optional.ofNullable(locks.getIfPresent(lockId));
  }

  LfsLock createLock(CurrentUser user, LfsCreateLockInput input) throws LfsException {
    log.atFine().log("Create lock for %s in project %s", input.path, project);
    String lockId = PathToLockId.CONVERTER.convert(input.path);
    LfsLock lock = locks.getIfPresent(lockId);
    if (lock != null) {
      throw new LfsLockExistsException(lock);
    }

    lock =
        new LfsLock(
            lockId, input.path, LfsDateTime.now(), new LfsLockOwner(user.getUserName().get()));
    LockFile fileLock = new LockFile(locksPath.resolve(lockId).toFile());
    try {
      if (!fileLock.lock()) {
        log.atWarning().log("Cannot lock path [%s] in project %s", input.path, project);
        throw new LfsLockExistsException(lock);
      }
    } catch (IOException e) {
      String error =
          String.format(
              "Locking path [%s] in project %s failed with error %s",
              input.path, project, e.getMessage());
      log.atWarning().log(error);
      throw new LfsException(error);
    }

    try {
      try (OutputStreamWriter out = new OutputStreamWriter(fileLock.getOutputStream())) {
        gson.toJson(lock, out);
      } catch (IOException e) {
        String error =
            String.format(
                "Locking path [%s] in project %s failed during write with error %s",
                input.path, project, e.getMessage());
        log.atWarning().log(error);
        throw new LfsException(error);
      }
      if (!fileLock.commit()) {
        String error =
            String.format("Committing lock to path [%s] in project %s failed", input.path, project);
        log.atWarning().log(error);
        throw new LfsException(error);
      }
      // put lock object to cache while file lock is being hold so that
      // there is no chance that other process performs lock operation
      // in the meantime (either cache returns with existing object or
      // LockFile.lock fails on locking attempt)
      locks.put(lockId, lock);
    } finally {
      fileLock.unlock();
    }

    return lock;
  }

  void deleteLock(LfsLock lock) throws LfsException {
    LockFile fileLock = new LockFile(locksPath.resolve(lock.id).toFile());
    try {
      if (!fileLock.lock()) {
        String error =
            String.format(
                "Deleting lock on path [%s] in project %s is not possible", lock.path, project);
        log.atWarning().log(error);
        throw new LfsException(error);
      }
    } catch (IOException e) {
      String error =
          String.format(
              "Getting lock on path [%s] in project %s failed with error %s",
              lock.path, project, e.getMessage());
      log.atWarning().log(error);
      throw new LfsException(error);
    }

    try {
      Files.deleteIfExists(locksPath.resolve(lock.id));
      locks.invalidate(lock.id);
    } catch (IOException e) {
      String error =
          String.format(
              "Deleting lock on path [%s] in project %s failed with error %s",
              lock.path, project, e.getMessage());
      log.atWarning().log(error);
      throw new LfsException(error);
    } finally {
      fileLock.unlock();
    }
  }

  Collection<LfsLock> getLocks() {
    return locks.asMap().values();
  }
}
