// 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 PathToLockId toLockId;
  private final String project;
  private final Path locksPath;
  private final Cache<String, LfsLock> locks;

  @Inject
  LfsProjectLocks(
      LfsGson gson,
      PathToLockId toLockId,
      LfsLocksPathProvider locksPath,
      @Assisted Project.NameKey project) {
    this.gson = gson;
    this.toLockId = toLockId;
    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 = toLockId.apply(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();
  }
}
