// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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.enterprise.adaptor;

import com.google.common.base.Objects;
import com.google.enterprise.adaptor.Principal.ParsedPrincipal;

import java.util.*;

/**
 * Transforms Principals in ACLs based on provided rules.
 */
final class AclTransform {
  private final List<Rule> rules;

  public AclTransform(List<Rule> rules) {
    this.rules = Collections.unmodifiableList(new ArrayList<Rule>(rules));
  }

  public Acl transform(Acl acl) {
    if (acl == null) {
      return null;
    }
    if (rules.isEmpty()) {
      return acl;
    }
    return new Acl.Builder(acl)
        .setPermits(transformInternal(acl.getPermits()))
        .setDenies(transformInternal(acl.getDenies()))
        .build();
  }

  public <T extends Principal> Collection<T> transform(
      Collection<T> principals) {
    if (rules.isEmpty()) {
      return principals;
    }
    return transformInternal(principals);
  }

  public <T extends Principal> T transform(T principal) {
    if (rules.isEmpty()) {
      return principal;
    }
    return transformInternal(principal);
  }

  private <T extends Principal> Collection<T> transformInternal(
      Collection<T> principals) {
    Collection<T> newPrincipals = new ArrayList<T>(principals.size());
    for (T principal : principals) {
      newPrincipals.add(transformInternal(principal));
    }
    return Collections.unmodifiableCollection(newPrincipals);
  }

  private <T extends Principal> T transformInternal(T principal) {
    ParsedPrincipal parsed = principal.parse();
    for (Rule rule : rules) {
      if (rule.match.matches(parsed)) {
        parsed = rule.replace.replace(parsed);
      }
    }
    @SuppressWarnings("unchecked")
    T principalNew = (T) parsed.toPrincipal();
    return principalNew;
  }

  @Override
  public String toString() {
    return "AclTransform(rules=" + rules + ")";
  }

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

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof AclTransform)) {
      return false;
    }
    AclTransform a = (AclTransform) o;
    return rules.equals(a.rules);
  }

  public static final class Rule {
    private final MatchData match;
    private final MatchData replace;

    public Rule(MatchData match, MatchData replace) {
      if (match == null || replace == null) {
        throw new NullPointerException();
      }
      if (replace.isGroup != null) {
        throw new IllegalArgumentException(
            "isGroup must be null for replacements");
      }
      this.match = match;
      this.replace = replace;
    }

    @Override
    public String toString() {
      return "Rule(match=" + match + ",replace=" + replace + ")";
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(new Object[] {match, replace});
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof Rule)) {
        return false;
      }
      Rule r = (Rule) o;
      return match.equals(r.match) && replace.equals(r.replace);
    }
  }

  public static final class MatchData {
    // Visible for GsaCommunicationHandler
    final Boolean isGroup;
    private final String name;
    private final String domain;
    private final String namespace;

    /**
     * For matching, non-{@code null} fields must be equal on Principal. For
     * replacing, non-{@code null} fields will get set on Principal.
     * {@code isGroup} must be {@code null} for replacements.
     */
    public MatchData(Boolean isGroup, String name, String domain,
        String namespace) {
      this.isGroup = isGroup;
      this.name = name;
      this.domain = domain;
      this.namespace = namespace;
    }

    private boolean matches(ParsedPrincipal principal) {
      boolean matches = true;
      if (isGroup != null) {
        matches = matches && isGroup.equals(principal.isGroup);
      }
      if (name != null) {
        matches = matches && name.equals(principal.plainName);
      }
      if (domain != null) {
        matches = matches && domain.equals(principal.domain);
      }
      if (namespace != null) {
        matches = matches && namespace.equals(principal.namespace);
      }
      return matches;
    }

    private ParsedPrincipal replace(ParsedPrincipal principal) {
      if (isGroup != null) {
        throw new AssertionError();
      }
      if (name != null) {
        principal = principal.plainName(name);
      }
      if (domain != null) {
        principal = principal.domain(domain);
      }
      if (namespace != null) {
        principal = principal.namespace(namespace);
      }
      return principal;
    }

    @Override
    public String toString() {
      return "MatchData(isGroup=" + isGroup + ",name=" + name
          + ",domain=" + domain + ",namespace=" + namespace + ")";
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(new Object[] {isGroup, name, domain, namespace});
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof MatchData)) {
        return false;
      }
      MatchData m = (MatchData) o;
      return Objects.equal(isGroup, m.isGroup)
          && Objects.equal(name, m.name)
          && Objects.equal(domain, m.domain)
          && Objects.equal(namespace, m.namespace);
    }
  }
}
