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

@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:
        break;

      case DENY:
        r.append("deny ");
        break;

      case BLOCK:
        r.append("block ");
        break;

      case INTERACTIVE:
        r.append("interactive ");
        break;

      case BATCH:
        r.append("batch ");
        break;
    }

    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 {
    public Builder setDeny() {
      return setAction(Action.DENY);
    }

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

    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();
  }
}
