// Copyright (C) 2008 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;

import com.google.gerrit.client.admin.AccountGroupDetail;
import com.google.gerrit.client.admin.GroupAdminService;
import com.google.gerrit.client.data.AccountInfoCacheFactory;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.reviewdb.AccountGroupMember;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.rpc.BaseServiceImplementation;
import com.google.gerrit.client.rpc.Common;
import com.google.gerrit.client.rpc.NameAlreadyUsedException;
import com.google.gerrit.client.rpc.NoSuchEntityException;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtjsonrpc.client.VoidResult;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Transaction;

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

public class GroupAdminServiceImpl extends BaseServiceImplementation implements
    GroupAdminService {
  public void ownedGroups(final AsyncCallback<List<AccountGroup>> callback) {
    run(callback, new Action<List<AccountGroup>>() {
      public List<AccountGroup> run(ReviewDb db) throws OrmException {
        final List<AccountGroup> result;
        if (Common.getGroupCache().isAdministrator(Common.getAccountId())) {
          result = db.accountGroups().all().toList();
        } else {
          result = myOwnedGroups(db);
          Collections.sort(result, new Comparator<AccountGroup>() {
            public int compare(final AccountGroup a, final AccountGroup b) {
              return a.getName().compareTo(b.getName());
            }
          });
        }
        return result;
      }
    });
  }

  public void createGroup(final String newName,
      final AsyncCallback<AccountGroup.Id> callback) {
    run(callback, new Action<AccountGroup.Id>() {
      public AccountGroup.Id run(final ReviewDb db) throws OrmException,
          Failure {
        final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName);
        if (db.accountGroups().get(nameKey) != null) {
          throw new Failure(new NameAlreadyUsedException());
        }

        final AccountGroup group =
            new AccountGroup(nameKey, new AccountGroup.Id(db
                .nextAccountGroupId()));
        group.setNameKey(nameKey);
        group.setDescription("");

        final AccountGroupMember m =
            new AccountGroupMember(new AccountGroupMember.Key(Common
                .getAccountId(), group.getId()));

        final Transaction txn = db.beginTransaction();
        db.accountGroups().insert(Collections.singleton(group), txn);
        db.accountGroupMembers().insert(Collections.singleton(m), txn);
        txn.commit();
        Common.getGroupCache().notifyGroupAdd(m);

        return group.getId();
      }
    });
  }

  public void groupDetail(final AccountGroup.Id groupId,
      final AsyncCallback<AccountGroupDetail> callback) {
    run(callback, new Action<AccountGroupDetail>() {
      public AccountGroupDetail run(ReviewDb db) throws OrmException, Failure {
        assertAmGroupOwner(db, groupId);
        final AccountGroup group = db.accountGroups().get(groupId);
        if (group == null) {
          throw new Failure(new NoSuchEntityException());
        }

        final AccountGroupDetail d = new AccountGroupDetail();
        final boolean auto = Common.getGroupCache().isAutoGroup(group.getId());
        d.load(db, new AccountInfoCacheFactory(db), group, auto);
        return d;
      }
    });
  }

  public void changeGroupDescription(final AccountGroup.Id groupId,
      final String description, final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(final ReviewDb db) throws OrmException, Failure {
        assertAmGroupOwner(db, groupId);
        final AccountGroup group = db.accountGroups().get(groupId);
        if (group == null) {
          throw new Failure(new NoSuchEntityException());
        }
        group.setDescription(description);
        db.accountGroups().update(Collections.singleton(group));
        return VoidResult.INSTANCE;
      }
    });
  }

  public void changeGroupOwner(final AccountGroup.Id groupId,
      final String newOwnerName, final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(final ReviewDb db) throws OrmException, Failure {
        assertAmGroupOwner(db, groupId);
        final AccountGroup group = db.accountGroups().get(groupId);
        if (group == null) {
          throw new Failure(new NoSuchEntityException());
        }

        final AccountGroup owner =
            db.accountGroups().get(new AccountGroup.NameKey(newOwnerName));
        if (owner == null) {
          throw new Failure(new NoSuchEntityException());
        }

        group.setOwnerGroupId(owner.getId());
        db.accountGroups().update(Collections.singleton(group));
        return VoidResult.INSTANCE;
      }
    });
  }

  public void renameGroup(final AccountGroup.Id groupId, final String newName,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(final ReviewDb db) throws OrmException, Failure {
        assertAmGroupOwner(db, groupId);
        final AccountGroup group = db.accountGroups().get(groupId);
        if (group == null) {
          throw new Failure(new NoSuchEntityException());
        }

        final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName);
        if (!nameKey.equals(group.getNameKey())) {
          if (db.accountGroups().get(nameKey) != null) {
            throw new Failure(new NameAlreadyUsedException());
          }
          group.setNameKey(nameKey);
          db.accountGroups().update(Collections.singleton(group));
        }
        return VoidResult.INSTANCE;
      }
    });
  }

  public void addGroupMember(final AccountGroup.Id groupId,
      final String nameOrEmail, final AsyncCallback<AccountGroupDetail> callback) {
    run(callback, new Action<AccountGroupDetail>() {
      public AccountGroupDetail run(ReviewDb db) throws OrmException, Failure {
        assertAmGroupOwner(db, groupId);
        if (Common.getGroupCache().isAutoGroup(groupId)) {
          throw new Failure(new NameAlreadyUsedException());
        }
        final Account a = findAccount(db, nameOrEmail);
        final AccountGroupMember.Key key =
            new AccountGroupMember.Key(a.getId(), groupId);
        if (db.accountGroupMembers().get(key) != null) {
          return new AccountGroupDetail();
        }

        final AccountGroupMember m = new AccountGroupMember(key);
        db.accountGroupMembers().insert(Collections.singleton(m));
        Common.getGroupCache().notifyGroupAdd(m);

        final AccountGroupDetail d = new AccountGroupDetail();
        d.loadOneMember(db, a, m);
        return d;
      }
    });
  }

  public void deleteGroupMembers(final Set<AccountGroupMember.Key> keys,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(final ReviewDb db) throws OrmException, Failure {
        final Set<AccountGroup.Id> owned = ids(myOwnedGroups(db));
        Boolean amAdmin = null;
        for (final AccountGroupMember.Key k : keys) {
          if (!owned.contains(k.getAccountGroupId())) {
            if (amAdmin == null) {
              amAdmin =
                  Common.getGroupCache().isAdministrator(Common.getAccountId());
            }
            if (!amAdmin) {
              throw new Failure(new NoSuchEntityException());
            }
          }
        }
        for (final AccountGroupMember.Key k : keys) {
          final AccountGroupMember m = db.accountGroupMembers().get(k);
          if (m != null) {
            db.accountGroupMembers().delete(Collections.singleton(m));
            Common.getGroupCache().notifyGroupDelete(m);
          }
        }
        return VoidResult.INSTANCE;
      }
    });
  }

  private void assertAmGroupOwner(final ReviewDb db,
      final AccountGroup.Id groupId) throws OrmException, Failure {
    final AccountGroup group = db.accountGroups().get(groupId);
    if (group == null) {
      throw new Failure(new NoSuchEntityException());
    }
    final Account.Id me = Common.getAccountId();
    if (!Common.getGroupCache().isInGroup(me, group.getOwnerGroupId())
        && !Common.getGroupCache().isAdministrator(me)) {
      throw new Failure(new NoSuchEntityException());
    }
  }

  private static Set<AccountGroup.Id> ids(
      final Collection<AccountGroup> groupList) {
    final HashSet<AccountGroup.Id> r = new HashSet<AccountGroup.Id>();
    for (final AccountGroup group : groupList) {
      r.add(group.getId());
    }
    return r;
  }

  private List<AccountGroup> myOwnedGroups(final ReviewDb db)
      throws OrmException {
    final Account.Id me = Common.getAccountId();
    final List<AccountGroup> own = new ArrayList<AccountGroup>();
    for (final AccountGroup.Id groupId : Common.getGroupCache().getEffectiveGroups(me)) {
      for (final AccountGroup g : db.accountGroups().ownedByGroup(groupId)) {
        own.add(g);
      }
    }
    return own;
  }

  private static Account findAccount(final ReviewDb db, final String nameOrEmail)
      throws OrmException, Failure {
    final Account r = Account.find(db, nameOrEmail);
    if (r == null) {
      throw new Failure(new NoSuchEntityException());
    }
    return r;
  }
}
