// 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.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.cache.CacheModule;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jgit.lfs.errors.LfsException;

@Singleton
class LfsLocksHandler {
  static class LfsLockExistsException extends LfsException {
    private static final long serialVersionUID = 1L;

    public final LfsLocksContext.Error error;

    public LfsLockExistsException(LfsLock lock) {
      super("Lock is already created");
      this.error = new LockError(getMessage(), lock);
    }
  }

  static class LockError extends LfsLocksContext.Error {
    public final LfsLock lock;

    LockError(String m, LfsLock lock) {
      super(m);
      this.lock = lock;
    }
  }

  private static final FluentLogger log = FluentLogger.forEnclosingClass();
  private static final String CACHE_NAME = "lfs_project_locks";

  static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        cache(CACHE_NAME, Project.NameKey.class, LfsProjectLocks.class).loader(Loader.class);
      }
    };
  }

  private final PathToLockId toLockId;
  private final LoadingCache<Project.NameKey, LfsProjectLocks> projectLocks;

  @Inject
  LfsLocksHandler(
      PathToLockId toLockId,
      @Named(CACHE_NAME) LoadingCache<Project.NameKey, LfsProjectLocks> projectLocks) {
    this.toLockId = toLockId;
    this.projectLocks = projectLocks;
  }

  LfsLockResponse createLock(Project.NameKey project, CurrentUser user, LfsCreateLockInput input)
      throws LfsException {
    log.atFine().log("Create lock for %s in project %s", input.path, project);
    LfsProjectLocks locks = projectLocks.getUnchecked(project);
    LfsLock lock = locks.createLock(user, input);
    return new LfsLockResponse(lock);
  }

  LfsLockResponse deleteLock(
      Project.NameKey project, CurrentUser user, String lockId, LfsDeleteLockInput input)
      throws LfsException {
    log.atFine().log(
        "Delete (-f %s) lock for %s in project %s",
        Boolean.TRUE.equals(input.force), lockId, project);
    LfsProjectLocks locks = projectLocks.getUnchecked(project);
    Optional<LfsLock> hasLock = locks.getLock(lockId);
    if (!hasLock.isPresent()) {
      throw new LfsException(
          String.format("there is no lock id %s in project %s", lockId, project));
    }

    LfsLock lock = hasLock.get();
    if (lock.owner.name.equals(user.getUserName().get())) {
      locks.deleteLock(lock);
      return new LfsLockResponse(lock);
    } else if (input.force) {
      locks.deleteLock(lock);
      return new LfsLockResponse(lock);
    }

    throw new LfsException(
        String.format("Lock %s is owned by different user %s", lockId, lock.owner.name));
  }

  LfsVerifyLocksResponse verifyLocks(Project.NameKey project, final CurrentUser user) {
    log.atFine().log("Verify list of locks for %s project and user %s", project, user);
    LfsProjectLocks locks = projectLocks.getUnchecked(project);
    Map<Boolean, List<LfsLock>> groupByOurs =
        locks.getLocks().stream()
            .collect(
                Collectors.groupingBy(
                    (in) -> {
                      return in.owner.name.equals(user.getUserName().get());
                    }));
    return new LfsVerifyLocksResponse(groupByOurs.get(true), groupByOurs.get(false), null);
  }

  LfsGetLocksResponse listLocksByPath(Project.NameKey project, String path) {
    log.atFine().log("Get lock for %s path in %s project", path, project);
    String lockId = toLockId.apply(path);
    return listLocksById(project, lockId);
  }

  LfsGetLocksResponse listLocksById(Project.NameKey project, String id) {
    log.atFine().log("Get lock for %s id in %s project", id, project);
    LfsProjectLocks locks = projectLocks.getUnchecked(project);
    Optional<LfsLock> lock = locks.getLock(id);
    List<LfsLock> locksById =
        (lock.isPresent() ? ImmutableList.of(lock.get()) : Collections.emptyList());
    return new LfsGetLocksResponse(locksById, null);
  }

  LfsGetLocksResponse listLocks(Project.NameKey project) {
    log.atFine().log("Get locks for %s project", project);
    return new LfsGetLocksResponse(projectLocks.getUnchecked(project).getLocks(), null);
  }

  static class Loader extends CacheLoader<Project.NameKey, LfsProjectLocks> {
    private final LfsProjectLocks.Factory factory;

    @Inject
    Loader(LfsProjectLocks.Factory factory) {
      this.factory = factory;
    }

    @Override
    public LfsProjectLocks load(Project.NameKey project) throws Exception {
      LfsProjectLocks locks = factory.create(project);
      locks.load();
      return locks;
    }
  }
}
