/*
 * 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.common.cloud;

import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.solr.common.cloud.Replica.Type;
import org.noggit.JSONWriter;

import static org.apache.solr.common.util.Utils.toJSONString;

/**
 * A Slice contains immutable information about a logical shard (all replicas that share the same shard id).
 */
public class Slice extends ZkNodeProps implements Iterable<Replica> {
  public final String collection;

  /** Loads multiple slices into a Map from a generic Map that probably came from deserialized JSON. */
  @SuppressWarnings({"unchecked"})
  public static Map<String,Slice> loadAllFromMap(String collection, Map<String, Object> genericSlices) {
    if (genericSlices == null) return Collections.emptyMap();
    Map<String, Slice> result = new LinkedHashMap<>(genericSlices.size());
    for (Map.Entry<String, Object> entry : genericSlices.entrySet()) {
      String name = entry.getKey();
      Object val = entry.getValue();
      if (val instanceof Slice) {
        result.put(name, (Slice) val);
      } else if (val instanceof Map) {
        result.put(name, new Slice(name, null, (Map<String, Object>) val, collection));
      }
    }
    return result;
  }

  @Override
  public Iterator<Replica> iterator() {
    return replicas.values().iterator();
  }

  /** The slice's state. */
  public enum State {

    /** The normal/default state of a shard. */
    ACTIVE,

    /**
     * A shard is put in that state after it has been successfully split. See
     * <a href="https://lucene.apache.org/solr/guide/collections-api.html#splitshard">
     * the reference guide</a> for more details.
     */
    INACTIVE,

    /**
     * When a shard is split, the new sub-shards are put in that state while the
     * split operation is in progress. It's also used when the shard is undergoing data restoration.
     * A shard in this state still receives
     * update requests from the parent shard leader, however does not participate
     * in distributed search.
     */
    CONSTRUCTION,

    /**
     * Sub-shards of a split shard are put in that state, when they need to
     * create replicas in order to meet the collection's replication factor. A
     * shard in that state still receives update requests from the parent shard
     * leader, however does not participate in distributed search.
     */
    RECOVERY,

    /**
     * Sub-shards of a split shard are put in that state when the split is deemed failed
     * by the overseer even though all replicas are active because either the leader node is
     * no longer live or has a different ephemeral owner (zk session id). Such conditions can potentially
     * lead to data loss. See SOLR-9438 for details. A shard in that state will neither receive
     * update requests from the parent shard leader, nor participate in distributed search.
     */
    RECOVERY_FAILED;

    @Override
    public String toString() {
      return super.toString().toLowerCase(Locale.ROOT);
    }

    /** Converts the state string to a State instance. */
    public static State getState(String stateStr) {
      return State.valueOf(stateStr.toUpperCase(Locale.ROOT));
    }
  }

  public static final String REPLICAS = "replicas";
  public static final String RANGE = "range";
  public static final String LEADER = "leader";       // FUTURE: do we want to record the leader as a slice property in the JSON (as opposed to isLeader as a replica property?)
  public static final String PARENT = "parent";

  private final String name;
  private final DocRouter.Range range;
  private final Integer replicationFactor;      // FUTURE: optional per-slice override of the collection replicationFactor
  private final Map<String,Replica> replicas;
  private final Replica leader;
  private final State state;
  private final String parent;
  private final Map<String, RoutingRule> routingRules;

  /**
   * @param name  The name of the slice
   * @param replicas The replicas of the slice.  This is used directly and a copy is not made.  If null, replicas will be constructed from props.
   * @param props  The properties of the slice - a shallow copy will always be made.
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Slice(String name, Map<String,Replica> replicas, Map<String,Object> props, String collection) {
    super( props==null ? new LinkedHashMap<String,Object>(2) : new LinkedHashMap<>(props));
    this.name = name;
    this.collection = collection;

    Object rangeObj = propMap.get(RANGE);
    if (propMap.get(ZkStateReader.STATE_PROP) != null) {
      this.state = State.getState((String) propMap.get(ZkStateReader.STATE_PROP));
    } else {
      this.state = State.ACTIVE;                         //Default to ACTIVE
      propMap.put(ZkStateReader.STATE_PROP, state.toString());
    }
    DocRouter.Range tmpRange = null;
    if (rangeObj instanceof DocRouter.Range) {
      tmpRange = (DocRouter.Range)rangeObj;
    } else if (rangeObj != null) {
      // Doesn't support custom implementations of Range, but currently not needed.
      tmpRange = DocRouter.DEFAULT.fromString(rangeObj.toString());
    }
    range = tmpRange;

    /** debugging.  this isn't an error condition for custom sharding.
    if (range == null) {
      System.out.println("###### NO RANGE for " + name + " props=" + props);
    }
    **/

    if (propMap.containsKey(PARENT) && propMap.get(PARENT) != null)
      this.parent = (String) propMap.get(PARENT);
    else
      this.parent = null;

    replicationFactor = null;  // future

    // add the replicas *after* the other properties (for aesthetics, so it's easy to find slice properties in the JSON output)
    this.replicas = replicas != null ? replicas : makeReplicas(collection,name, (Map<String,Object>)propMap.get(REPLICAS));
    propMap.put(REPLICAS, this.replicas);

    Map<String, Object> rules = (Map<String, Object>) propMap.get("routingRules");
    if (rules != null) {
      this.routingRules = new HashMap<>();
      for (Map.Entry<String, Object> entry : rules.entrySet()) {
        Object o = entry.getValue();
        if (o instanceof Map) {
          Map map = (Map) o;
          RoutingRule rule = new RoutingRule(entry.getKey(), map);
          routingRules.put(entry.getKey(), rule);
        } else {
          routingRules.put(entry.getKey(), (RoutingRule) o);
        }
      }
    } else {
      this.routingRules = null;
    }

    leader = findLeader();
  }


  @SuppressWarnings({"unchecked"})
  private Map<String,Replica> makeReplicas(String collection, String slice,Map<String,Object> genericReplicas) {
    if (genericReplicas == null) return new HashMap<>(1);
    Map<String,Replica> result = new LinkedHashMap<>(genericReplicas.size());
    for (Map.Entry<String,Object> entry : genericReplicas.entrySet()) {
      String name = entry.getKey();
      Object val = entry.getValue();
      Replica r;
      if (val instanceof Replica) {
        r = (Replica)val;
      } else {
        r = new Replica(name, (Map<String,Object>)val, collection, slice);
      }
      result.put(name, r);
    }
    return result;
  }

  private Replica findLeader() {
    for (Replica replica : replicas.values()) {
      if (replica.getStr(LEADER) != null) {
        assert replica.getType() == Type.TLOG || replica.getType() == Type.NRT: "Pull replica should not become leader!";
        return replica;
      }
    }
    return null;
  }

  public String getCollection() {
    return collection;
  }
  /**
   * Return slice name (shard id).
   */
  public String getName() {
    return name;
  }

  /**
   * Gets the list of all replicas for this slice.
   */
  public Collection<Replica> getReplicas() {
    return replicas.values();
  }

  /**
   * Gets all replicas that match a predicate
   */
  public List<Replica> getReplicas(Predicate<Replica> pred) {
    return replicas.values().stream().filter(pred).collect(Collectors.toList());
  }

  /**
   * Gets the list of replicas that have a type present in s
   */
  public List<Replica> getReplicas(EnumSet<Replica.Type> s) {
    return this.getReplicas(r->s.contains(r.getType()));
  }

  /**
   * Get the map of coreNodeName to replicas for this slice.
   */
  public Map<String, Replica> getReplicasMap() {
    return replicas;
  }

  public Map<String,Replica> getReplicasCopy() {
    return new LinkedHashMap<>(replicas);
  }

  public Replica getLeader() {
    return leader;
  }

  public Replica getReplica(String replicaName) {
    return replicas.get(replicaName);
  }

  public DocRouter.Range getRange() {
    return range;
  }

  public State getState() {
    return state;
  }

  public String getParent() {
    return parent;
  }

  public Map<String, RoutingRule> getRoutingRules() {
    return routingRules;
  }

  @Override
  public String toString() {
    return name + ':' + toJSONString(propMap);
  }

  @Override
  public void write(JSONWriter jsonWriter) {
    jsonWriter.write(propMap);
  }

}
