/*
 * 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.client.solrj.request;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.request.beans.V2ApiConstants;
import org.apache.solr.common.params.CollectionParams.CollectionAction;
import org.apache.solr.common.util.CommandOperation;
import org.apache.solr.common.util.Pair;
import org.apache.solr.common.util.Utils;

import static org.apache.solr.client.solrj.SolrRequest.METHOD.DELETE;
import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.COLLECTION_STATE;
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.PER_COLLECTION;
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.PER_COLLECTION_PER_SHARD_COMMANDS;
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.PER_COLLECTION_PER_SHARD_DELETE;
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.PER_COLLECTION_PER_SHARD_PER_REPLICA_DELETE;
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.PER_COLLECTION_SHARDS_COMMANDS;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICA;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.BALANCESHARDUNIQUE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CLUSTERSTATUS;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.COLLECTIONPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATESHARD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETEREPLICA;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETEREPLICAPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETESHARD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MIGRATE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MODIFYCOLLECTION;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MOVEREPLICA;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.REBALANCELEADERS;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.RELOAD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.SPLITSHARD;
import static org.apache.solr.common.params.CommonParams.NAME;

/**
 * Stores the mapping of v1 API parameters to v2 API parameters
 * for the collection API and the configset API.
 */
public class CollectionApiMapping {

  public enum Meta implements CommandMeta {
    GET_A_COLLECTION(COLLECTION_STATE, GET, CLUSTERSTATUS),
    RELOAD_COLL(PER_COLLECTION,
        POST,
        RELOAD,
        RELOAD.toLower(),
        Utils.makeMap(NAME, "collection")),
    MODIFY_COLLECTION(PER_COLLECTION,
        POST,
        MODIFYCOLLECTION,
        "modify",null),
    MIGRATE_DOCS(PER_COLLECTION,
        POST,
        MIGRATE,
        "migrate-docs",
        Utils.makeMap("split.key", "splitKey",
            "target.collection", "target",
            "forward.timeout", "forwardTimeout"
        )),
    MOVE_REPLICA(PER_COLLECTION,
        POST, MOVEREPLICA, "move-replica", null),
    REBALANCE_LEADERS(PER_COLLECTION,
        POST,
        REBALANCELEADERS,
        "rebalance-leaders", null),
    CREATE_SHARD(PER_COLLECTION_SHARDS_COMMANDS,
        POST,
        CREATESHARD,
        "create",
        Utils.makeMap("createNodeSet", V2ApiConstants.NODE_SET),
        Utils.makeMap("property.", "coreProperties.")) {
      @Override
      public String getParamSubstitute(String param) {
        return super.getParamSubstitute(param);
      }
    },

    SPLIT_SHARD(PER_COLLECTION_SHARDS_COMMANDS,
        POST,
        SPLITSHARD,
        "split",
        Utils.makeMap(
            "split.key", "splitKey"),
        Utils.makeMap("property.", "coreProperties.")),
    DELETE_SHARD(PER_COLLECTION_PER_SHARD_DELETE,
        DELETE, DELETESHARD),

    CREATE_REPLICA(PER_COLLECTION_SHARDS_COMMANDS,
        POST,
        ADDREPLICA,
        "add-replica",
        null,
        Utils.makeMap("property.", "coreProperties.")),

    DELETE_REPLICA(PER_COLLECTION_PER_SHARD_PER_REPLICA_DELETE,
        DELETE, DELETEREPLICA),

    SYNC_SHARD(PER_COLLECTION_PER_SHARD_COMMANDS,
        POST,
        CollectionAction.SYNCSHARD,
        "synch-shard",
        null),
    ADD_REPLICA_PROPERTY(PER_COLLECTION,
        POST,
        CollectionAction.ADDREPLICAPROP,
        "add-replica-property",
        Utils.makeMap("property", "name", "property.value", "value")),
    DELETE_REPLICA_PROPERTY(PER_COLLECTION,
        POST,
        DELETEREPLICAPROP,
        "delete-replica-property",
        null),
    SET_COLLECTION_PROPERTY(PER_COLLECTION,
        POST,
        COLLECTIONPROP,
        "set-collection-property",
        Utils.makeMap(
            NAME, "collection",
            "propertyName", "name",
            "propertyValue", "value")),
    FORCE_LEADER(PER_COLLECTION_PER_SHARD_COMMANDS, POST, CollectionAction.FORCELEADER, "force-leader", null),
    BALANCE_SHARD_UNIQUE(PER_COLLECTION, POST, BALANCESHARDUNIQUE,"balance-shard-unique" , null)
    ;

    public final String commandName;
    public final EndPoint endPoint;
    public final SolrRequest.METHOD method;
    public final CollectionAction action;

    //bi-directional mapping of v1 http param name to v2 json attribute
    public final Map<String, String> paramsToAttrs; // v1 -> v2
    public final Map<String, String> attrsToParams; // v2 -> v1
    //mapping of old prefix to new for instance properties.a=val can be substituted with property:{a:val}
    public final Map<String, String> prefixParamsToAttrs; // v1 -> v2

    public SolrRequest.METHOD getMethod() {
      return method;
    }


    Meta(EndPoint endPoint, SolrRequest.METHOD method, CollectionAction action) {
      this(endPoint, method, action, null, null);
    }

    Meta(EndPoint endPoint, SolrRequest.METHOD method, CollectionAction action,
         String commandName,
         @SuppressWarnings({"rawtypes"})Map paramsToAttrs) {
      this(endPoint, method, action, commandName, paramsToAttrs, Collections.emptyMap());
    }

    // lame... the Maps aren't typed simply because callers want to use Utils.makeMap which yields object vals
    @SuppressWarnings("unchecked")
    Meta(EndPoint endPoint, SolrRequest.METHOD method, CollectionAction action,
         String commandName,
         @SuppressWarnings({"rawtypes"})Map paramsToAttrs,
         @SuppressWarnings({"rawtypes"})Map prefixParamsToAttrs) {
      this.action = action;
      this.commandName = commandName;
      this.endPoint = endPoint;
      this.method = method;

      this.paramsToAttrs = paramsToAttrs == null ? Collections.emptyMap() : Collections.unmodifiableMap(paramsToAttrs);
      this.attrsToParams = Collections.unmodifiableMap(reverseMap(this.paramsToAttrs));
      this.prefixParamsToAttrs = prefixParamsToAttrs == null ? Collections.emptyMap() : Collections.unmodifiableMap(prefixParamsToAttrs);
    }

    private static Map<String, String> reverseMap(Map<String, String> input) { // swap keys and values
      Map<String, String> attrToParams = new HashMap<>(input.size());
      for (Map.Entry<String, String> entry :input.entrySet()) {
        final String existing = attrToParams.put(entry.getValue(), entry.getKey());
        if (existing != null) {
          throw new IllegalArgumentException("keys and values must collectively be unique");
        }
      }
      return attrToParams;
    }

    @Override
    public String getName() {
      return commandName;
    }

    @Override
    public SolrRequest.METHOD getHttpMethod() {
      return method;
    }

    @Override
    public V2EndPoint getEndPoint() {
      return endPoint;
    }

    // Returns iterator of v1 "params".
    @Override
    public Iterator<String> getParamNamesIterator(CommandOperation op) {
      Collection<String> paramNames = getParamNames_(op, this);
      Stream<String> pStream = paramNames.stream();
      if (!attrsToParams.isEmpty()) {
        pStream = pStream.map(paramName -> attrsToParams.getOrDefault(paramName, paramName));
      }
      if (!prefixParamsToAttrs.isEmpty()) {
        pStream = pStream.map(paramName -> {
          for (Map.Entry<String, String> e : prefixParamsToAttrs.entrySet()) {
            final String prefixV1 = e.getKey();
            final String prefixV2 = e.getValue();
            if (paramName.startsWith(prefixV2)) {
              return prefixV1 + paramName.substring(prefixV2.length()); // replace
            }
          }
          return paramName;
        });
      }
      return pStream.iterator();
    }

    // returns params (v1) from an underlying v2, with param (v1) input
    @Override
    public String getParamSubstitute(String param) {//input is v1
      for (Map.Entry<String, String> e : prefixParamsToAttrs.entrySet()) {
        final String prefixV1 = e.getKey();
        final String prefixV2 = e.getValue();
        if (param.startsWith(prefixV1)) {
          return prefixV2 + param.substring(prefixV1.length()); // replace
        }
      }
      return paramsToAttrs.getOrDefault(param, param);
    }

    // TODO document!
    public Object getReverseParamSubstitute(String param) {//input is v1
      for (Map.Entry<String, String> e : prefixParamsToAttrs.entrySet()) {
        final String prefixV1 = e.getKey();
        final String prefixV2 = e.getValue();
        if (param.startsWith(prefixV1)) {
          return new Pair<>(prefixV2.substring(0, prefixV2.length() - 1), param.substring(prefixV1.length()));
        }
      }
      return paramsToAttrs.getOrDefault(param, param);
    }

  }

  public enum EndPoint implements V2EndPoint {
    COLLECTION_STATE("collections.collection"),
    PER_COLLECTION("collections.collection.Commands"),
    PER_COLLECTION_SHARDS_COMMANDS("collections.collection.shards.Commands"),
    PER_COLLECTION_PER_SHARD_COMMANDS("collections.collection.shards.shard.Commands"),
    PER_COLLECTION_PER_SHARD_DELETE("collections.collection.shards.shard.delete"),
    PER_COLLECTION_PER_SHARD_PER_REPLICA_DELETE("collections.collection.shards.shard.replica.delete");
    final String specName;


    EndPoint(String specName) {
      this.specName = specName;
    }

    @Override
    public String getSpecName() {
      return specName;
    }
  }

  public interface V2EndPoint {

    String getSpecName();
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private static Collection<String> getParamNames_(CommandOperation op, CommandMeta command) {
    Object o = op.getCommandData();
    if (o instanceof Map) {
      Map map = (Map) o;
      List<String> result = new ArrayList<>();
      collectKeyNames(map, result, "");
      return result;
    } else {
      return Collections.emptySet();
    }
  }

  @SuppressWarnings({"unchecked"})
  public static void collectKeyNames(Map<String, Object> map, List<String> result, String prefix) {
    for (Map.Entry<String, Object> e : map.entrySet()) {
      if (e.getValue() instanceof Map) {
        collectKeyNames((Map) e.getValue(), result, prefix + e.getKey() + ".");
      } else {
        result.add(prefix + e.getKey());
      }
    }
  }
  public interface CommandMeta {
    String getName();

    /**
     * the http method supported by this command
     */
    SolrRequest.METHOD getHttpMethod();

    V2EndPoint getEndPoint();

    default Iterator<String> getParamNamesIterator(CommandOperation op) {
      return getParamNames_(op, CommandMeta.this).iterator();
    }

    /** Given a v1 param, return the v2 attribute (possibly a dotted path). */
    default String getParamSubstitute(String name) {
      return name;
    }
  }
}
