// Copyright (C) 2014 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.serviceuser;

import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change.Id;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.group.ListMembers;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import com.googlesource.gerrit.plugins.serviceuser.GetServiceUser.ServiceUserInfo;

import org.eclipse.jgit.lib.PersonIdent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@Singleton
class ServiceUserResolver {
  private final AccountResolver resolver;
  private final IdentifiedUser.GenericFactory genericUserFactory;
  private final Provider<GetServiceUser> getServiceUser;
  private final Provider<ListMembers> listMembers;
  private final SchemaFactory<ReviewDb> schema;
  private final ThreadLocalRequestContext tl;
  private final AccountCache accountCache;

  @Inject
  ServiceUserResolver(AccountResolver resolver,
      IdentifiedUser.GenericFactory genericUserFactory,
      Provider<GetServiceUser> getServiceUser,
      Provider<ListMembers> listMembers, SchemaFactory<ReviewDb> schema,
      ThreadLocalRequestContext tl, AccountCache accountCache) {
    this.resolver = resolver;
    this.genericUserFactory = genericUserFactory;
    this.getServiceUser = getServiceUser;
    this.listMembers = listMembers;
    this.schema = schema;
    this.tl = tl;
    this.accountCache = accountCache;
  }

  ServiceUserInfo getAsServiceUser(PersonIdent committerIdent)
      throws OrmException {
    StringBuilder committer = new StringBuilder();
    committer.append(committerIdent.getName());
    committer.append(" <");
    committer.append(committerIdent.getEmailAddress());
    committer.append("> ");

    try (ReviewDb db = schema.open())  {
      Account account = resolver.find(db, committer.toString());
      if (account == null) {
        return null;
      }
      try {
        return getServiceUser.get().apply(
            new ServiceUserResource(genericUserFactory.create(account.getId())));
      } catch (ResourceNotFoundException e) {
        return null;
      }
    }
  }

  List<AccountInfo> listOwners(ServiceUserInfo serviceUser) throws OrmException {
    if (serviceUser.owner == null) {
      return Collections.emptyList();
    }

    try (ReviewDb db = schema.open()) {
      RequestContext context = new RequestContext() {
        @Override
        public CurrentUser getUser() {
          return new CurrentUser(null) {

            @Override
            public GroupMembership getEffectiveGroups() {
              return new GroupMembership() {
                @Override
                public Set<AccountGroup.UUID> intersection(Iterable<AccountGroup.UUID> groupIds) {
                  return null;
                }

                @Override
                public Set<AccountGroup.UUID> getKnownGroups() {
                  return null;
                }

                @Override
                public boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds) {
                  return true;
                }

                @Override
                public boolean contains(AccountGroup.UUID groupId) {
                  return true;
                }
              };
            }
          };
        }

        @Override
        public Provider<ReviewDb> getReviewDbProvider() {
          return new Provider<ReviewDb>() {
            @Override
            public ReviewDb get() {
              return db;
            }};
        }
      };
      RequestContext old = tl.setContext(context);
      try {
        ListMembers lm = listMembers.get();
        lm.setRecursive(true);
        List<AccountInfo> owners = new ArrayList<>();
        for (AccountInfo a : lm.apply(new AccountGroup.UUID(serviceUser.owner.id))) {
          owners.add(a);
        }
        return owners;
      } finally {
        tl.setContext(old);
      }
    }
  }

  List<AccountInfo> listActiveOwners(ServiceUserInfo serviceUser)
      throws OrmException {
    List<AccountInfo> activeOwners = new ArrayList<>();
    for (AccountInfo owner : listOwners(serviceUser)) {
      AccountState accountState = accountCache.get(new Account.Id(owner._accountId));
      if (accountState != null && accountState.getAccount().isActive()) {
        activeOwners.add(owner);
      }
    }
    return activeOwners;
  }
}

@@ -892,60 +892,8 @@
 up;%0A
-import com.google.gerrit.reviewdb.client.Change.Id;%0A
 impo
@@ -1778,37 +1778,8 @@
 st;%0A
-import java.util.Collection;%0A
 impo

Remove unused imports