// Copyright (C) 2017 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.permissions;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.gerrit.server.permissions.LabelPermission.ForUser.ON_BEHALF_OF;
import static com.google.gerrit.server.permissions.LabelPermission.ForUser.SELF;

import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelValue;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.server.util.LabelVote;
import java.util.Optional;

/** Permission representing a label. */
public class LabelPermission implements ChangePermissionOrLabel {
  public enum ForUser {
    SELF,
    ON_BEHALF_OF;
  }

  private final ForUser forUser;
  private final String name;

  /**
   * Construct a reference to a label permission.
   *
   * @param type type description of the label.
   */
  public LabelPermission(LabelType type) {
    this(SELF, type);
  }

  /**
   * Construct a reference to a label permission.
   *
   * @param forUser {@code SELF} (default) or {@code ON_BEHALF_OF} for labelAs behavior.
   * @param type type description of the label.
   */
  public LabelPermission(ForUser forUser, LabelType type) {
    this(forUser, type.getName());
  }

  /**
   * Construct a reference to a label permission.
   *
   * @param name name of the label, e.g. {@code "Code-Review"} or {@code "Verified"}.
   */
  public LabelPermission(String name) {
    this(SELF, name);
  }

  /**
   * Construct a reference to a label permission.
   *
   * @param forUser {@code SELF} (default) or {@code ON_BEHALF_OF} for labelAs behavior.
   * @param name name of the label, e.g. {@code "Code-Review"} or {@code "Verified"}.
   */
  public LabelPermission(ForUser forUser, String name) {
    this.forUser = checkNotNull(forUser, "ForUser");
    this.name = LabelType.checkName(name);
  }

  /** @return {@code SELF} or {@code ON_BEHALF_OF} (or labelAs). */
  public ForUser forUser() {
    return forUser;
  }

  /** @return name of the label, e.g. {@code "Code-Review"}. */
  public String label() {
    return name;
  }

  /** @return name used in {@code project.config} permissions. */
  @Override
  public Optional<String> permissionName() {
    switch (forUser) {
      case SELF:
        return Optional.of(Permission.forLabel(name));
      case ON_BEHALF_OF:
        return Optional.of(Permission.forLabelAs(name));
    }
    return Optional.empty();
  }

  @Override
  public String describeForException() {
    if (forUser == ON_BEHALF_OF) {
      return "labelAs " + name;
    }
    return "label " + name;
  }

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

  @Override
  public boolean equals(Object other) {
    if (other instanceof LabelPermission) {
      LabelPermission b = (LabelPermission) other;
      return forUser == b.forUser && name.equals(b.name);
    }
    return false;
  }

  @Override
  public String toString() {
    if (forUser == ON_BEHALF_OF) {
      return "LabelAs[" + name + ']';
    }
    return "Label[" + name + ']';
  }

  /** A {@link LabelPermission} at a specific value. */
  public static class WithValue implements ChangePermissionOrLabel {
    private final ForUser forUser;
    private final LabelVote label;

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param type description of the label.
     * @param value numeric score assigned to the label.
     */
    public WithValue(LabelType type, LabelValue value) {
      this(SELF, type, value);
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param type description of the label.
     * @param value numeric score assigned to the label.
     */
    public WithValue(LabelType type, short value) {
      this(SELF, type.getName(), value);
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param forUser {@code SELF} (default) or {@code ON_BEHALF_OF} for labelAs behavior.
     * @param type description of the label.
     * @param value numeric score assigned to the label.
     */
    public WithValue(ForUser forUser, LabelType type, LabelValue value) {
      this(forUser, type.getName(), value.getValue());
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param forUser {@code SELF} (default) or {@code ON_BEHALF_OF} for labelAs behavior.
     * @param type description of the label.
     * @param value numeric score assigned to the label.
     */
    public WithValue(ForUser forUser, LabelType type, short value) {
      this(forUser, type.getName(), value);
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param name name of the label, e.g. {@code "Code-Review"} or {@code "Verified"}.
     * @param value numeric score assigned to the label.
     */
    public WithValue(String name, short value) {
      this(SELF, name, value);
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param forUser {@code SELF} (default) or {@code ON_BEHALF_OF} for labelAs behavior.
     * @param name name of the label, e.g. {@code "Code-Review"} or {@code "Verified"}.
     * @param value numeric score assigned to the label.
     */
    public WithValue(ForUser forUser, String name, short value) {
      this(forUser, LabelVote.create(name, value));
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param label label name and vote.
     */
    public WithValue(LabelVote label) {
      this(SELF, label);
    }

    /**
     * Construct a reference to a label at a specific value.
     *
     * @param forUser {@code SELF} (default) or {@code ON_BEHALF_OF} for labelAs behavior.
     * @param label label name and vote.
     */
    public WithValue(ForUser forUser, LabelVote label) {
      this.forUser = checkNotNull(forUser, "ForUser");
      this.label = checkNotNull(label, "LabelVote");
    }

    /** @return {@code SELF} or {@code ON_BEHALF_OF} (or labelAs). */
    public ForUser forUser() {
      return forUser;
    }

    /** @return name of the label, e.g. {@code "Code-Review"}. */
    public String label() {
      return label.label();
    }

    /** @return specific value of the label, e.g. 1 or 2. */
    public short value() {
      return label.value();
    }

    /** @return name used in {@code project.config} permissions. */
    @Override
    public Optional<String> permissionName() {
      switch (forUser) {
        case SELF:
          return Optional.of(Permission.forLabel(label()));
        case ON_BEHALF_OF:
          return Optional.of(Permission.forLabelAs(label()));
      }
      return Optional.empty();
    }

    @Override
    public String describeForException() {
      if (forUser == ON_BEHALF_OF) {
        return "labelAs " + label.formatWithEquals();
      }
      return "label " + label.formatWithEquals();
    }

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

    @Override
    public boolean equals(Object other) {
      if (other instanceof WithValue) {
        WithValue b = (WithValue) other;
        return forUser == b.forUser && label.equals(b.label);
      }
      return false;
    }

    @Override
    public String toString() {
      if (forUser == ON_BEHALF_OF) {
        return "LabelAs[" + label.format() + ']';
      }
      return "Label[" + label.format() + ']';
    }
  }
}
