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

import com.google.gerrit.server.CurrentUser;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
class LfsSshRequestAuthorizer {
  static class SshAuthInfo extends AuthInfo {
    SshAuthInfo(String authToken, Instant issued, Long expiresIn) {
      super(SSH_AUTH_PREFIX + authToken, issued, expiresIn);
    }
  }

  private static final Logger log = LoggerFactory.getLogger(LfsSshRequestAuthorizer.class);
  private static final int DEFAULT_SSH_TIMEOUT = 10;
  static final String SSH_AUTH_PREFIX = "Ssh: ";
  private final Processor processor;
  private final Long expiresIn;

  @Inject
  LfsSshRequestAuthorizer(Processor processor, LfsConfigurationFactory configFactory) {
    this.processor = processor;
    long timeout = DEFAULT_SSH_TIMEOUT;
    try {
      timeout =
          configFactory
              .getGlobalConfig()
              .getInt("auth", null, "sshExpirationSeconds", DEFAULT_SSH_TIMEOUT);
    } catch (IllegalArgumentException e) {
      log.warn(
          "Reading expiration timeout failed with error." + " Falling back to default {}",
          DEFAULT_SSH_TIMEOUT,
          e);
    }
    this.expiresIn = timeout;
  }

  SshAuthInfo generateAuthInfo(CurrentUser user, String project, String operation) {
    LfsSshAuthToken token =
        new LfsSshAuthToken(user.getUserName().get(), project, operation, Instant.now(), expiresIn);
    return new SshAuthInfo(processor.serialize(token), token.issued, token.expiresIn);
  }

  Optional<String> getUserFromValidToken(String authToken, String project, String operation) {
    Optional<LfsSshAuthToken> token = processor.deserialize(authToken);
    if (!token.isPresent()) {
      return Optional.empty();
    }
    Verifier verifier = new Verifier(token.get(), project, operation);
    if (!verifier.verify()) {
      log.error("Invalid data was provided with auth token {}.", authToken);
      return Optional.empty();
    }
    return Optional.of(token.get().user);
  }

  static class Processor extends LfsAuthToken.Processor<LfsSshAuthToken> {
    @Inject
    protected Processor(LfsCipher cipher) {
      super(cipher);
    }

    @Override
    protected List<String> getValues(LfsSshAuthToken token) {
      List<String> values = new ArrayList<>(4);
      values.add(token.user);
      values.add(token.project);
      values.add(token.operation);
      values.add(LfsDateTime.format(token.issued));
      values.add(String.valueOf(token.expiresIn));
      return values;
    }

    @Override
    protected Optional<LfsSshAuthToken> createToken(List<String> values) {
      if (values.size() != 5) {
        return Optional.empty();
      }
      return Optional.of(
          new LfsSshAuthToken(
              values.get(0),
              values.get(1),
              values.get(2),
              values.get(3),
              Long.valueOf(values.get(4))));
    }
  }

  private static class Verifier extends LfsAuthToken.Verifier<LfsSshAuthToken> {
    private final String project;
    private final String operation;

    protected Verifier(LfsSshAuthToken token, String project, String operation) {
      super(token);
      this.project = project;
      this.operation = operation;
    }

    @Override
    protected boolean verifyTokenValues() {
      return project.equals(token.project) && operation.equals(token.operation);
    }
  }

  private static class LfsSshAuthToken extends LfsAuthToken {
    private final String user;
    private final String project;
    private final String operation;

    LfsSshAuthToken(String user, String project, String operation, Instant issued, Long expiresIn) {
      super(issued, expiresIn);
      this.user = user;
      this.project = project;
      this.operation = operation;
    }

    LfsSshAuthToken(String user, String project, String operation, String issued, Long expiresIn) {
      super(issued, expiresIn);
      this.user = user;
      this.project = project;
      this.operation = operation;
    }
  }
}
