/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.sentry.policy.common;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.sentry.core.common.BitFieldAction;
import org.apache.sentry.core.common.BitFieldActionFactory;
import org.apache.sentry.core.common.ImplyMethodType;
import org.apache.sentry.core.common.Model;
import org.apache.sentry.core.common.utils.KeyValue;
import org.apache.sentry.core.common.utils.PathUtils;
import org.apache.sentry.core.common.utils.SentryConstants;

import java.util.List;

// The class is used to compare the privilege
public class CommonPrivilege implements Privilege {

  private ImmutableList<KeyValue> parts;

  public CommonPrivilege(String privilegeStr) {
    privilegeStr = Strings.nullToEmpty(privilegeStr).trim();
    if (privilegeStr.isEmpty()) {
      throw new IllegalArgumentException("Privilege string cannot be null or empty.");
    }
    List<KeyValue> parts = Lists.newArrayList();
    for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.trimResults().split(
            privilegeStr)) {
      if (authorizable.isEmpty()) {
        throw new IllegalArgumentException("Privilege '" + privilegeStr + "' has an empty section");
      }
      parts.add(new KeyValue(authorizable));
    }
    if (parts.isEmpty()) {
      throw new AssertionError("Should never occur: " + privilegeStr);
    }
    this.parts = ImmutableList.copyOf(parts);
  }

  public boolean implies(Privilege privilege, Model model) {
    // By default only supports comparisons with other IndexerWildcardPermissions
    if (!(privilege instanceof CommonPrivilege)) {
      return false;
    }

    List<KeyValue> otherParts = ((CommonPrivilege) privilege).getParts();
    if(parts.equals(otherParts)) {
      return true;
    }

    int index = 0;
    for (KeyValue otherPart : otherParts) {
      // If this privilege has less parts than the other privilege, everything
      // after the number of parts contained
      // in this privilege is automatically implied, so return true
      if (parts.size() - 1 < index) {
        return true;
      } else {
        KeyValue part = parts.get(index);
        String policyKey = part.getKey();
        // are the keys even equal
        if(!policyKey.equalsIgnoreCase(otherPart.getKey())) {
          // Support for action inheritance from parent to child
          if (SentryConstants.PRIVILEGE_NAME.equalsIgnoreCase(policyKey)) {
            continue;
          }
          return false;
        }

        // do the imply for action
        if (SentryConstants.PRIVILEGE_NAME.equalsIgnoreCase(policyKey)) {
          if (!impliesAction(part.getValue(), otherPart.getValue(), model.getBitFieldActionFactory())) {
            return false;
          }
        } else {
          if (!impliesResource(model.getImplyMethodMap().get(policyKey), part.getValue(), otherPart.getValue())) {
            return false;
          }
        }

        index++;
      }
    }

    // If this privilege has more parts than the other parts, only imply it if
    // all of the other parts are wildcards
    for (; index < parts.size(); index++) {
      KeyValue part = parts.get(index);
      if (!SentryConstants.PRIVILEGE_WILDCARD_VALUE.equals(part.getValue())) {
        return false;
      }
    }

    return true;
  }

  // The method is used for compare the value of resource by the ImplyMethodType.
  // for Hive, databaseName, tableName, columnName will be compared using String.equal(wildcard support)
  //           url will be compared using PathUtils.impliesURI
  private boolean impliesResource(ImplyMethodType implyMethodType, String policyValue, String requestValue) {
    // wildcard support, "*", "+", "all"("+" and "all" are for backward compatibility) are represented as wildcard
    // if requestValue is wildcard, means privilege request is to match with any value of given resource
    if (SentryConstants.RESOURCE_WILDCARD_VALUE.equals(policyValue)
            || SentryConstants.RESOURCE_WILDCARD_VALUE.equals(requestValue)
            || SentryConstants.RESOURCE_WILDCARD_VALUE_ALL.equals(policyValue)
            || SentryConstants.RESOURCE_WILDCARD_VALUE_ALL.equals(requestValue)
            || SentryConstants.RESOURCE_WILDCARD_VALUE_SOME.equals(policyValue)
            || SentryConstants.RESOURCE_WILDCARD_VALUE_SOME.equals(requestValue)) {
      return true;
    }

    // compare as the url
    if (ImplyMethodType.URL == implyMethodType) {
      return PathUtils.impliesURI(policyValue, requestValue);
    }
    // default: compare as the string
    return policyValue.equals(requestValue);
  }

  // The method is used for compare the action for the privilege model.
  // for Hive, the action will be select, insert, etc.
  // for Solr, the action will be update, query, etc.
  private boolean impliesAction(String policyValue, String requestValue,
                                BitFieldActionFactory bitFieldActionFactory) {
    BitFieldAction currentAction = bitFieldActionFactory.getActionByName(policyValue);
    BitFieldAction requestAction = bitFieldActionFactory.getActionByName(requestValue);
    // the action in privilege is not supported
    if (currentAction == null || requestAction == null) {
      return false;
    }
    return currentAction.implies(requestAction);
  }

  @Override
  public String toString() {
    return SentryConstants.AUTHORIZABLE_JOINER.join(parts);
  }

  public boolean implies(Privilege p) {
    return false;
  }

  public List<KeyValue> getParts() {
    return parts;
  }

  @Override
  public boolean equals(Object o) {
    if (o instanceof CommonPrivilege) {
      CommonPrivilege cp = (CommonPrivilege) o;
      return parts.equals(cp.parts);
    }
    return false;
  }

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