// Copyright (C) 2009 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.account;

import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountExternalId;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.AccountGroupMember;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.cache.Cache;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.EntryCreator;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/** Caches important (but small) account state to avoid database hits. */
@Singleton
public class AccountCacheImpl implements AccountCache {
  private static final String BYID_NAME = "accounts";
  private static final String BYUSER_NAME = "accounts_byname";

  public static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        final TypeLiteral<Cache<Account.Id, AccountState>> byIdType =
            new TypeLiteral<Cache<Account.Id, AccountState>>() {};
        core(byIdType, BYID_NAME).populateWith(ByIdLoader.class);

        final TypeLiteral<Cache<String, Account.Id>> byUsernameType =
            new TypeLiteral<Cache<String, Account.Id>>() {};
        core(byUsernameType, BYUSER_NAME).populateWith(ByNameLoader.class);

        bind(AccountCacheImpl.class);
        bind(AccountCache.class).to(AccountCacheImpl.class);
      }
    };
  }

  private final Cache<Account.Id, AccountState> byId;
  private final Cache<String, Account.Id> byName;

  @Inject
  AccountCacheImpl(@Named(BYID_NAME) Cache<Account.Id, AccountState> byId,
      @Named(BYUSER_NAME) Cache<String, Account.Id> byUsername) {
    this.byId = byId;
    this.byName = byUsername;
  }

  public AccountState get(final Account.Id accountId) {
    return byId.get(accountId);
  }

  @Override
  public AccountState getByUsername(String username) {
    Account.Id id = byName.get(username);
    return id != null ? byId.get(id) : null;
  }

  public void evict(final Account.Id accountId) {
    byId.remove(accountId);
  }

  public void evictByUsername(String username) {
    byName.remove(username);
  }

  static class ByIdLoader extends EntryCreator<Account.Id, AccountState> {
    private final SchemaFactory<ReviewDb> schema;
    private final Set<AccountGroup.Id> registered;
    private final Set<AccountGroup.Id> anonymous;
    private final GroupCache groupCache;
    private final Cache<String, Account.Id> byName;

    @Inject
    ByIdLoader(SchemaFactory<ReviewDb> sf, AuthConfig auth,
        GroupCache groupCache,
        @Named(BYUSER_NAME) Cache<String, Account.Id> byUsername) {
      this.schema = sf;
      this.registered = auth.getRegisteredGroups();
      this.anonymous = auth.getAnonymousGroups();
      this.groupCache = groupCache;
      this.byName = byUsername;
    }

    @Override
    public AccountState createEntry(final Account.Id key) throws Exception {
      final ReviewDb db = schema.open();
      try {
        final AccountState state = load(db, key);
        if (state.getUserName() != null) {
          byName.put(state.getUserName(), state.getAccount().getId());
        }
        return state;
      } finally {
        db.close();
      }
    }

    private AccountState load(final ReviewDb db, final Account.Id who)
        throws OrmException {
      final Account account = db.accounts().get(who);
      if (account == null) {
        // Account no longer exists? They are anonymous.
        //
        return missing(who);
      }

      final Collection<AccountExternalId> externalIds =
          Collections.unmodifiableCollection(db.accountExternalIds().byAccount(
              who).toList());

      Set<AccountGroup.Id> internalGroups = new HashSet<AccountGroup.Id>();
      for (AccountGroupMember g : db.accountGroupMembers().byAccount(who)) {
        final AccountGroup.Id groupId = g.getAccountGroupId();
        final AccountGroup group = groupCache.get(groupId);
        if (group != null && group.getType() == AccountGroup.Type.INTERNAL) {
          internalGroups.add(groupId);
        }
      }

      if (internalGroups.isEmpty()) {
        internalGroups = registered;
      } else {
        internalGroups.addAll(registered);
        internalGroups = Collections.unmodifiableSet(internalGroups);
      }

      return new AccountState(account, internalGroups, externalIds);
    }

    @Override
    public AccountState missing(final Account.Id accountId) {
      final Account account = new Account(accountId);
      final Collection<AccountExternalId> ids = Collections.emptySet();
      return new AccountState(account, anonymous, ids);
    }
  }

  static class ByNameLoader extends EntryCreator<String, Account.Id> {
    private final SchemaFactory<ReviewDb> schema;

    @Inject
    ByNameLoader(final SchemaFactory<ReviewDb> sf) {
      this.schema = sf;
    }

    @Override
    public Account.Id createEntry(final String username) throws Exception {
      final ReviewDb db = schema.open();
      try {
        final AccountExternalId.Key key = new AccountExternalId.Key( //
            AccountExternalId.SCHEME_USERNAME, //
            username);
        final AccountExternalId id = db.accountExternalIds().get(key);
        return id != null ? id.getAccountId() : null;
      } finally {
        db.close();
      }
    }
  }
}
