/*
 * 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.solr.security;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.apache.solr.common.util.CommandOperation;

import static org.apache.solr.common.util.Utils.getDeepCopy;
import static org.apache.solr.handler.admin.SecurityConfHandler.getListValue;
import static org.apache.solr.handler.admin.SecurityConfHandler.getMapValue;

enum AutorizationEditOperation {
  SET_USER_ROLE("set-user-role") {
    @Override
    public Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op) {
      Map<String, Object> roleMap = getMapValue(latestConf, "user-role");
      Map<String, Object> map = op.getDataMap();
      if (op.hasError()) return null;
      for (Map.Entry<String, Object> e : map.entrySet()) {
        if (e.getValue() == null) {
          roleMap.remove(e.getKey());
          continue;
        }
        if (e.getValue() instanceof String || e.getValue() instanceof List) {
          roleMap.put(e.getKey(), e.getValue());
        } else {
          op.addError("Unexpected value ");
          return null;
        }
      }
      return latestConf;
    }
  },
  SET_PERMISSION("set-permission") {
    @Override
    @SuppressWarnings({"unchecked"})
    public Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op) {
      Integer index = op.getInt("index", null);
      Integer beforeIdx = op.getInt("before",null);
      Map<String, Object> dataMap = op.getDataMap();
      if (op.hasError()) return null;
      dataMap = getDeepCopy(dataMap, 3);
      dataMap.remove("before");
      if (beforeIdx != null && index != null) {
        op.addError("Cannot use 'index' and 'before together ");
        return null;
      }

      for (String key : dataMap.keySet()) {
        if (!Permission.knownKeys.contains(key)) op.addError("Unknown key, " + key);
      }
      try {
        Permission.load(dataMap);
      } catch (Exception e) {
        op.addError(e.getMessage());
        return null;
      }
      if(op.hasError()) return null;
      @SuppressWarnings({"rawtypes"})
      List<Map> permissions = getListValue(latestConf, "permissions");
      setIndex(permissions);
      @SuppressWarnings({"rawtypes"})
      List<Map> permissionsCopy = new ArrayList<>();
      boolean beforeSatisfied = beforeIdx == null;
      boolean indexSatisfied = index == null;
      for (int i = 0; i < permissions.size(); i++) {
        @SuppressWarnings({"rawtypes"})
        Map perm = permissions.get(i);
        Integer thisIdx = (Integer) perm.get("index");
        if (thisIdx.equals(beforeIdx)) {
          beforeSatisfied = true;
          permissionsCopy.add(dataMap);
          permissionsCopy.add(perm);
        } else if (thisIdx.equals(index)) {
          //overwriting an existing one
          indexSatisfied = true;
          permissionsCopy.add(dataMap);
        } else {
          permissionsCopy.add(perm);
        }
      }

      if (!beforeSatisfied) {
        op.addError("Invalid 'before' :" + beforeIdx);
        return null;
      }
      if (!indexSatisfied) {
        op.addError("Invalid 'index' :" + index);
        return null;
      }

      if (!permissionsCopy.contains(dataMap)) permissionsCopy.add(dataMap);
      latestConf.put("permissions", permissionsCopy);
      setIndex(permissionsCopy);
      return latestConf;
    }

  },
  UPDATE_PERMISSION("update-permission") {
    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op) {
      Integer index = op.getInt("index");
      if (op.hasError()) return null;
      List<Map> permissions = (List<Map>) getListValue(latestConf, "permissions");
      setIndex(permissions);
      for (Map permission : permissions) {
        if (index.equals(permission.get("index"))) {
          LinkedHashMap copy = new LinkedHashMap<>(permission);
          copy.putAll(op.getDataMap());
          op.setCommandData(copy);
          return SET_PERMISSION.edit(latestConf, op);
        }
      }
      op.addError("No such permission " + name);
      return null;
    }
  },
  DELETE_PERMISSION("delete-permission") {
    @Override
    @SuppressWarnings({"unchecked"})
    public Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op) {
      Integer id = op.getInt("");
      if(op.hasError()) return null;
      @SuppressWarnings({"rawtypes"})
      List<Map> p = getListValue(latestConf, "permissions");
      setIndex(p);
      @SuppressWarnings({"rawtypes"})
      List<Map> c = p.stream().filter(map -> !id.equals(map.get("index"))).collect(Collectors.toList());
      if(c.size() == p.size()){
        op.addError("No such index :"+ id);
        return null;
      }
      latestConf.put("permissions", c);
      return latestConf;
    }
  };

  public abstract Map<String, Object> edit(Map<String, Object> latestConf, CommandOperation op);

  public final String name;

  public String getOperationName() {
    return name;
  }

  AutorizationEditOperation(String s) {
    this.name = s;
  }

  public static AutorizationEditOperation get(String name) {
    for (AutorizationEditOperation o : values()) if (o.name.equals(name)) return o;
    return null;
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  static void setIndex(List<Map> permissionsCopy) {
    AtomicInteger counter = new AtomicInteger(0);
    permissionsCopy.stream().forEach(map -> map.put("index", counter.incrementAndGet()));
  }
}
