// Copyright (C) 2010 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.common.data;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

/** A single permission within an {@link AccessSection} of a project. */
public class Permission implements Comparable<Permission> {
  public static final String ABANDON = "abandon";
  public static final String CREATE = "create";
  public static final String DELETE_DRAFTS = "deleteDrafts";
  public static final String EDIT_TOPIC_NAME = "editTopicName";
  public static final String FORGE_AUTHOR = "forgeAuthor";
  public static final String FORGE_COMMITTER = "forgeCommitter";
  public static final String FORGE_SERVER = "forgeServerAsCommitter";
  public static final String LABEL = "label-";
  public static final String OWNER = "owner";
  public static final String PUBLISH_DRAFTS = "publishDrafts";
  public static final String PUSH = "push";
  public static final String PUSH_MERGE = "pushMerge";
  public static final String PUSH_TAG = "pushTag";
  public static final String PUSH_SIGNED_TAG = "pushSignedTag";
  public static final String READ = "read";
  public static final String REBASE = "rebase";
  public static final String REMOVE_REVIEWER = "removeReviewer";
  public static final String SUBMIT = "submit";
  public static final String VIEW_DRAFTS = "viewDrafts";

  private static final List<String> NAMES_LC;
  private static final int labelIndex;

  static {
    NAMES_LC = new ArrayList<String>();
    NAMES_LC.add(OWNER.toLowerCase());
    NAMES_LC.add(READ.toLowerCase());
    NAMES_LC.add(ABANDON.toLowerCase());
    NAMES_LC.add(CREATE.toLowerCase());
    NAMES_LC.add(FORGE_AUTHOR.toLowerCase());
    NAMES_LC.add(FORGE_COMMITTER.toLowerCase());
    NAMES_LC.add(FORGE_SERVER.toLowerCase());
    NAMES_LC.add(PUSH.toLowerCase());
    NAMES_LC.add(PUSH_MERGE.toLowerCase());
    NAMES_LC.add(PUSH_TAG.toLowerCase());
    NAMES_LC.add(PUSH_SIGNED_TAG.toLowerCase());
    NAMES_LC.add(LABEL.toLowerCase());
    NAMES_LC.add(REBASE.toLowerCase());
    NAMES_LC.add(REMOVE_REVIEWER.toLowerCase());
    NAMES_LC.add(SUBMIT.toLowerCase());
    NAMES_LC.add(VIEW_DRAFTS.toLowerCase());
    NAMES_LC.add(EDIT_TOPIC_NAME.toLowerCase());
    NAMES_LC.add(DELETE_DRAFTS.toLowerCase());
    NAMES_LC.add(PUBLISH_DRAFTS.toLowerCase());

    labelIndex = NAMES_LC.indexOf(Permission.LABEL);
  }

  /** @return true if the name is recognized as a permission name. */
  public static boolean isPermission(String varName) {
    String lc = varName.toLowerCase();
    if (lc.startsWith(LABEL)) {
      return LABEL.length() < lc.length();
    }
    return NAMES_LC.contains(lc);
  }

  /** @return true if the permission name is actually for a review label. */
  public static boolean isLabel(String varName) {
    return varName.startsWith(LABEL) && LABEL.length() < varName.length();
  }

  /** @return permission name for the given review label. */
  public static String forLabel(String labelName) {
    return LABEL + labelName;
  }

  public static boolean canBeOnAllProjects(String ref, String permissionName) {
    if (AccessSection.ALL.equals(ref)) {
      return !OWNER.equals(permissionName);
    }
    return true;
  }

  protected String name;
  protected boolean exclusiveGroup;
  protected List<PermissionRule> rules;

  protected Permission() {
  }

  public Permission(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public boolean isLabel() {
    return isLabel(getName());
  }

  public String getLabel() {
    if (isLabel()) {
      return getName().substring(LABEL.length());
    }
    return null;
  }

  public Boolean getExclusiveGroup() {
    // Only permit exclusive group behavior on non OWNER permissions,
    // otherwise an owner might lose access to a delegated subspace.
    //
    return exclusiveGroup && !OWNER.equals(getName());
  }

  public void setExclusiveGroup(Boolean newExclusiveGroup) {
    exclusiveGroup = newExclusiveGroup;
  }

  public List<PermissionRule> getRules() {
    initRules();
    return rules;
  }

  public void setRules(List<PermissionRule> list) {
    rules = list;
  }

  public void add(PermissionRule rule) {
    initRules();
    rules.add(rule);
  }

  public void remove(PermissionRule rule) {
    if (rule != null) {
      removeRule(rule.getGroup());
    }
  }

  public void removeRule(GroupReference group) {
    if (rules != null) {
      for (Iterator<PermissionRule> itr = rules.iterator(); itr.hasNext();) {
        if (sameGroup(itr.next(), group)) {
          itr.remove();
        }
      }
    }
  }

  public PermissionRule getRule(GroupReference group) {
    return getRule(group, false);
  }

  public PermissionRule getRule(GroupReference group, boolean create) {
    initRules();

    for (PermissionRule r : rules) {
      if (sameGroup(r, group)) {
        return r;
      }
    }

    if (create) {
      PermissionRule r = new PermissionRule(group);
      rules.add(r);
      return r;
    } else {
      return null;
    }
  }

  void mergeFrom(Permission src) {
    for (PermissionRule srcRule : src.getRules()) {
      PermissionRule dstRule = getRule(srcRule.getGroup());
      if (dstRule != null) {
        dstRule.mergeFrom(srcRule);
      } else {
        add(srcRule);
      }
    }
  }

  private static boolean sameGroup(PermissionRule rule, GroupReference group) {
    if (group.getUUID() != null) {
      return group.getUUID().equals(rule.getGroup().getUUID());

    } else if (group.getName() != null) {
      return group.getName().equals(rule.getGroup().getName());

    } else {
      return false;
    }
  }

  private void initRules() {
    if (rules == null) {
      rules = new ArrayList<PermissionRule>(4);
    }
  }

  @Override
  public int compareTo(Permission b) {
    int cmp = index(this) - index(b);
    if (cmp == 0) {
      cmp = getName().compareTo(b.getName());
    }
    return cmp;
  }

  private static int index(Permission a) {
    if (a.isLabel()) {
      return labelIndex;
    }

    int index = NAMES_LC.indexOf(a.getName().toLowerCase());
    return 0 <= index ? index : NAMES_LC.size();
  }

  @Override
  public boolean equals(final Object obj) {
    if (!(obj instanceof Permission)) {
      return false;
    }

    final Permission other = (Permission) obj;
    if (!name.equals(other.name) || exclusiveGroup != other.exclusiveGroup) {
      return false;
    }
    return new HashSet<PermissionRule>(rules)
        .equals(new HashSet<PermissionRule>(other.rules));
  }

  @Override
  public int hashCode() {
    return name.hashCode();
  }
}
