// 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.google.gerrit.server.notedb;

import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdCache;
import com.google.gerrit.server.config.GerritServerId;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Optional;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.util.GitDateFormatter;
import org.eclipse.jgit.util.GitDateFormatter.Format;

@Singleton
public class NoteDbUtil {

  private final String serverId;
  private final ExternalIdCache externalIdCache;

  @Inject
  public NoteDbUtil(@GerritServerId String serverId, ExternalIdCache externalIdCache) {
    this.serverId = serverId;
    this.externalIdCache = externalIdCache;
  }

  private static final CharMatcher INVALID_FOOTER_CHARS = CharMatcher.anyOf("\r\n\0");

  private static final ImmutableList<String> PACKAGE_PREFIXES =
      ImmutableList.of("com.google.gerrit.server.", "com.google.gerrit.");
  private static final ImmutableSet<String> SERVLET_NAMES =
      ImmutableSet.of("com.google.gerrit.httpd.restapi.RestApiServlet");

  /**
   * Returns an AccountId for the given person's identity and the current serverId. Reverse lookup
   * the AccountId using the ExternalIdCache if the account has a foreign serverId.
   *
   * @param ident the accountId@serverId identity
   * @return a defined accountId if the account was found, {@link Account#UNKNOWN_ACCOUNT_ID} if the
   *     lookup via external-id did not return any account, or an empty value if the identity was
   *     malformed.
   */
  public Optional<Account.Id> parseIdent(PersonIdent ident) {
    return parseIdent(ident.getEmailAddress());
  }

  /**
   * Returns an AccountId for the given email address and the current serverId. Reverse lookup the
   * AccountId using the ExternalIdCache if the account has a foreign serverId.
   *
   * @param email the accountId@serverId email identity
   * @return a defined accountId if the account was found, {@link Account#UNKNOWN_ACCOUNT_ID} if the
   *     lookup via external-id did not return any account, or an empty value if the identity was
   *     malformed.
   */
  public Optional<Account.Id> parseIdent(String email) {
    int at = email.indexOf('@');
    if (at >= 0) {
      Integer id = Ints.tryParse(email.substring(0, at));
      String accountServerId = email.substring(at + 1);
      if (id != null) {
        if (accountServerId.equals(serverId)) {
          return Optional.of(Account.id(id));
        }

        ExternalId.Key extIdKey = ExternalId.Key.create(ExternalId.SCHEME_IMPORTED, email, false);
        try {
          return externalIdCache
              .byKey(extIdKey)
              .map(ExternalId::accountId)
              .or(() -> Optional.of(Account.UNKNOWN_ACCOUNT_ID));
        } catch (IOException e) {
          throw new IllegalArgumentException("Unable to lookup external id from cache", e);
        }
      }
    }
    return Optional.empty();
  }

  public static String extractHostPartFromPersonIdent(PersonIdent ident) {
    String email = ident.getEmailAddress();
    int at = email.indexOf('@');
    if (at >= 0) {
      return email.substring(at + 1);
    }
    throw new IllegalArgumentException("No host part found: " + email);
  }

  public static String formatTime(PersonIdent ident, Timestamp t) {
    GitDateFormatter dateFormatter = new GitDateFormatter(Format.DEFAULT);
    // TODO(dborowitz): Use a ThreadLocal or use Joda.
    PersonIdent newIdent = new PersonIdent(ident, t);
    return dateFormatter.formatDate(newIdent);
  }

  /**
   * Returns the name of the REST API handler that is in the stack trace of the caller of this
   * method.
   */
  static String guessRestApiHandler() {
    StackTraceElement[] trace = Thread.currentThread().getStackTrace();
    int i = findRestApiServlet(trace);
    if (i < 0) {
      i = findApiImpl(trace);
    }
    if (i < 0) {
      return null;
    }
    try {
      for (i--; i >= 0; i--) {
        String cn = trace[i].getClassName();
        Class<?> cls = Class.forName(cn);
        if (RestModifyView.class.isAssignableFrom(cls)) {
          return viewName(cn);
        }
      }
      return null;
    } catch (ClassNotFoundException e) {
      return null;
    }
  }

  static String sanitizeFooter(String value) {
    // Remove characters that would confuse JGit's footer parser if they were
    // included in footer values, for example by splitting the footer block into
    // multiple paragraphs.
    //
    // One painful example: RevCommit#getShorMessage() might return a message
    // containing "\r\r", which RevCommit#getFooterLines() will treat as an
    // empty paragraph for the purposes of footer parsing.
    return INVALID_FOOTER_CHARS.trimAndCollapseFrom(value, ' ');
  }

  private static int findRestApiServlet(StackTraceElement[] trace) {
    for (int i = 0; i < trace.length; i++) {
      if (SERVLET_NAMES.contains(trace[i].getClassName())) {
        return i;
      }
    }
    return -1;
  }

  private static int findApiImpl(StackTraceElement[] trace) {
    for (int i = 0; i < trace.length; i++) {
      String clazz = trace[i].getClassName();
      if (clazz.startsWith("com.google.gerrit.server.api.") && clazz.endsWith("ApiImpl")) {
        return i;
      }
    }
    return -1;
  }

  private static String viewName(String cn) {
    String impl = cn.replace('$', '.');
    for (String p : PACKAGE_PREFIXES) {
      if (impl.startsWith(p)) {
        return impl.substring(p.length());
      }
    }
    return impl;
  }
}
