// 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.httpd.rpc.project;

import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.InheritedRefRight;
import com.google.gerrit.common.data.ProjectDetail;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.RefRight;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.RefControl;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

class ProjectDetailFactory extends Handler<ProjectDetail> {
  interface Factory {
    ProjectDetailFactory create(@Assisted Project.NameKey name);
  }

  private final ApprovalTypes approvalTypes;
  private final GroupCache groupCache;
  private final ProjectControl.Factory projectControlFactory;

  private final Project.NameKey projectName;
  private Map<AccountGroup.Id, AccountGroup> groups;

  @Inject
  ProjectDetailFactory(final ApprovalTypes approvalTypes,
      final GroupCache groupCache,
      final ProjectControl.Factory projectControlFactory,

      @Assisted final Project.NameKey name) {
    this.approvalTypes = approvalTypes;
    this.groupCache = groupCache;
    this.projectControlFactory = projectControlFactory;

    this.projectName = name;
  }

  @Override
  public ProjectDetail call() throws NoSuchProjectException {
    final ProjectControl pc =
        projectControlFactory.validateFor(projectName, ProjectControl.OWNER
            | ProjectControl.VISIBLE);
    final ProjectState projectState = pc.getProjectState();
    final ProjectDetail detail = new ProjectDetail();
    detail.setProject(projectState.getProject());

    groups = new HashMap<AccountGroup.Id, AccountGroup>();
    final List<InheritedRefRight> refRights = new ArrayList<InheritedRefRight>();

    for (final RefRight r : projectState.getInheritedRights()) {
      RefControl rc = pc.controlForRef(r.getRefPattern());
      boolean isOwner = rc.isOwner();

      if (!isOwner && !rc.isVisible()) {
        continue;
      }

      InheritedRefRight refRight = new InheritedRefRight(r, true, isOwner);
      if (!refRights.contains(refRight)) {
        refRights.add(refRight);
        wantGroup(r.getAccountGroupId());
      }
    }

    for (final RefRight r : projectState.getLocalRights()) {
      RefControl rc = pc.controlForRef(r.getRefPattern());
      boolean isOwner = rc.isOwner();

      if (!isOwner && !rc.isVisible()) {
        continue;
      }

      refRights.add(new InheritedRefRight(r, false, isOwner));
      wantGroup(r.getAccountGroupId());
    }

    loadGroups();

    Collections.sort(refRights, new Comparator<InheritedRefRight>() {
      @Override
      public int compare(final InheritedRefRight a, final InheritedRefRight b) {
        final RefRight right1 = a.getRight();
        final RefRight right2 = b.getRight();
        int rc = categoryOf(right1).compareTo(categoryOf(right2));
        if (rc == 0) {
          rc = right1.getRefPattern().compareTo(right2.getRefPattern());
        }
        if (rc == 0) {
          rc = groupOf(right1).compareTo(groupOf(right2));
        }
        return rc;
      }

      private String categoryOf(final RefRight r) {
        final ApprovalType type =
            approvalTypes.getApprovalType(r.getApprovalCategoryId());
        if (type == null) {
          return r.getApprovalCategoryId().get();
        }
        return type.getCategory().getName();
      }

      private String groupOf(final RefRight r) {
        return groups.get(r.getAccountGroupId()).getName();
      }
    });

    final boolean userIsOwner = pc.isOwner();
    final boolean userIsOwnerAnyRef = pc.isOwnerAnyRef();

    detail.setRights(refRights);
    detail.setGroups(groups);
    detail.setCanModifyAccess(userIsOwnerAnyRef);
    detail.setCanModifyAgreements(userIsOwner);
    detail.setCanModifyDescription(userIsOwner);
    detail.setCanModifyMergeType(userIsOwner);
    return detail;
  }

  private void wantGroup(final AccountGroup.Id id) {
    groups.put(id, null);
  }

  private void loadGroups() {
    final Set<AccountGroup.Id> toGet = groups.keySet();
    groups = new HashMap<AccountGroup.Id, AccountGroup>();
    for (AccountGroup.Id groupId : toGet) {
      groups.put(groupId, groupCache.get(groupId));
    }
  }
}
