// 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.entities;

import com.google.auto.value.AutoValue;
import com.google.errorprone.annotations.CanIgnoreReturnValue;

@AutoValue
public abstract class PermissionRule implements Comparable<PermissionRule> {
  public static final boolean DEF_FORCE = false;

  public enum Action {
    ALLOW,
    DENY,
    BLOCK,

    INTERACTIVE,
    BATCH
  }

  public abstract Action getAction();

  public abstract boolean getForce();

  public abstract int getMin();

  public abstract int getMax();

  public abstract GroupReference getGroup();

  public static PermissionRule.Builder builder(GroupReference group) {
    return builder().setGroup(group);
  }

  public static PermissionRule create(GroupReference group) {
    return builder().setGroup(group).build();
  }

  protected static Builder builder() {
    return new AutoValue_PermissionRule.Builder()
        .setMin(0)
        .setMax(0)
        .setAction(Action.ALLOW)
        .setForce(DEF_FORCE);
  }

  static PermissionRule merge(PermissionRule src, PermissionRule dest) {
    PermissionRule.Builder result = dest.toBuilder();
    if (dest.getAction() != src.getAction()) {
      if (dest.getAction() == Action.BLOCK || src.getAction() == Action.BLOCK) {
        result.setAction(Action.BLOCK);

      } else if (dest.getAction() == Action.DENY || src.getAction() == Action.DENY) {
        result.setAction(Action.DENY);

      } else if (dest.getAction() == Action.BATCH || src.getAction() == Action.BATCH) {
        result.setAction(Action.BATCH);
      }
    }

    result.setForce(dest.getForce() || src.getForce());
    result.setRange(Math.min(dest.getMin(), src.getMin()), Math.max(dest.getMax(), src.getMax()));
    return result.build();
  }

  public boolean isDeny() {
    return getAction() == Action.DENY;
  }

  public boolean isBlock() {
    return getAction() == Action.BLOCK;
  }

  @Override
  public int compareTo(PermissionRule o) {
    int cmp = action(this) - action(o);
    if (cmp == 0) {
      cmp = range(o) - range(this);
    }
    if (cmp == 0) {
      cmp = group(this).compareTo(group(o));
    }
    return cmp;
  }

  private static int action(PermissionRule a) {
    switch (a.getAction()) {
      case DENY:
        return 0;
      case ALLOW:
      case BATCH:
      case BLOCK:
      case INTERACTIVE:
      default:
        return 1 + a.getAction().ordinal();
    }
  }

  private static int range(PermissionRule a) {
    return Math.abs(a.getMin()) + Math.abs(a.getMax());
  }

  private static String group(PermissionRule a) {
    return a.getGroup().getName() != null ? a.getGroup().getName() : "";
  }

  @Override
  public final String toString() {
    return asString(true);
  }

  public String asString(boolean canUseRange) {
    StringBuilder r = new StringBuilder();

    switch (getAction()) {
      case ALLOW -> {}
      case DENY -> r.append("deny ");
      case BLOCK -> r.append("block ");
      case INTERACTIVE -> r.append("interactive ");
      case BATCH -> r.append("batch ");
    }

    if (getForce()) {
      r.append("+force ");
    }

    if (canUseRange && (getMin() != 0 || getMax() != 0)) {
      if (0 <= getMin()) {
        r.append('+');
      }
      r.append(getMin());
      r.append("..");
      if (0 <= getMax()) {
        r.append('+');
      }
      r.append(getMax());
      r.append(' ');
    }

    r.append(getGroup().toConfigValue());

    return r.toString();
  }

  public static PermissionRule fromString(String src, boolean mightUseRange) {
    final String orig = src;
    final PermissionRule.Builder rule = PermissionRule.builder();

    src = src.trim();

    if (src.startsWith("deny ")) {
      rule.setAction(Action.DENY);
      src = src.substring("deny ".length()).trim();

    } else if (src.startsWith("block ")) {
      rule.setAction(Action.BLOCK);
      src = src.substring("block ".length()).trim();

    } else if (src.startsWith("interactive ")) {
      rule.setAction(Action.INTERACTIVE);
      src = src.substring("interactive ".length()).trim();

    } else if (src.startsWith("batch ")) {
      rule.setAction(Action.BATCH);
      src = src.substring("batch ".length()).trim();
    }

    if (src.startsWith("+force ")) {
      rule.setForce(true);
      src = src.substring("+force ".length()).trim();
    }

    if (mightUseRange && !GroupReference.isGroupReference(src)) {
      int sp = src.indexOf(' ');
      String range = src.substring(0, sp);

      if (range.matches("^([+-]?\\d+)\\.\\.([+-]?\\d+)$")) {
        int dotdot = range.indexOf("..");
        int min = parseInt(range.substring(0, dotdot));
        int max = parseInt(range.substring(dotdot + 2));
        if (min > max) {
          throw new IllegalArgumentException("Invalid range in rule: " + orig);
        }
        rule.setRange(min, max);
      } else {
        throw new IllegalArgumentException("Invalid range in rule: " + orig);
      }

      src = src.substring(sp + 1).trim();
    }

    String groupName = GroupReference.extractGroupName(src);
    if (groupName != null) {
      GroupReference group = GroupReference.create(groupName);
      rule.setGroup(group);
    } else {
      throw new IllegalArgumentException("Rule must include group: " + orig);
    }

    return rule.build();
  }

  public boolean hasRange() {
    return getMin() != 0 || getMax() != 0;
  }

  public static int parseInt(String value) {
    if (value.startsWith("+")) {
      value = value.substring(1);
    }
    return Integer.parseInt(value);
  }

  public abstract Builder toBuilder();

  @AutoValue.Builder
  public abstract static class Builder {
    @CanIgnoreReturnValue
    public Builder setDeny() {
      return setAction(Action.DENY);
    }

    @CanIgnoreReturnValue
    public Builder setBlock() {
      return setAction(Action.BLOCK);
    }

    @CanIgnoreReturnValue
    public Builder setRange(int newMin, int newMax) {
      if (newMax < newMin) {
        setMin(newMax);
        setMax(newMin);
      } else {
        setMin(newMin);
        setMax(newMax);
      }
      return this;
    }

    public abstract Builder setAction(Action action);

    public abstract Builder setGroup(GroupReference groupReference);

    public abstract Builder setForce(boolean newForce);

    public abstract Builder setMin(int min);

    public abstract Builder setMax(int max);

    public abstract GroupReference getGroup();

    public abstract PermissionRule build();
  }
}
