/*
 * 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;


import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;

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

/**
 * Use this class to push all entries of a Map into an output.
 * This avoids creating map instances and is supposed to be memory efficient.
 * If the entries are primitives, unnecessary boxing is also avoided.
 */
public interface MapWriter extends MapSerializable , NavigableObject {

  default String jsonStr(){
    return Utils.toJSONString(this);
  }

  @Override
  default Map toMap(Map<String, Object> map) {
    try {
      writeMap(new EntryWriter() {
        @Override
        public EntryWriter put(CharSequence k, Object v) {
          if (v instanceof MapWriter) v = ((MapWriter) v).toMap(new LinkedHashMap<>());
          if (v instanceof IteratorWriter) v = ((IteratorWriter) v).toList(new ArrayList<>());
          if (v instanceof Iterable) {
            List lst = new ArrayList();
            for (Object vv : (Iterable)v) {
              if (vv instanceof MapWriter) vv = ((MapWriter) vv).toMap(new LinkedHashMap<>());
              if (vv instanceof IteratorWriter) vv = ((IteratorWriter) vv).toList(new ArrayList<>());
              lst.add(vv);
            }
            v = lst;
          }
          if (v instanceof Map) {
            Map map = new LinkedHashMap();
            for (Map.Entry<?, ?> entry : ((Map<?, ?>)v).entrySet()) {
              Object vv = entry.getValue();
              if (vv instanceof MapWriter) vv = ((MapWriter) vv).toMap(new LinkedHashMap<>());
              if (vv instanceof IteratorWriter) vv = ((IteratorWriter) vv).toList(new ArrayList<>());
              map.put(entry.getKey(), vv);
            }
            v = map;
          }
          map.put(k==null? null : k.toString(), v);
          // note: It'd be nice to assert that there is no previous value at 'k' but it's possible the passed in
          // map is already populated and the intention is to overwrite.
          return this;
        }

      });
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return map;
  }

  void writeMap(EntryWriter ew) throws IOException;

  /**
   * An interface to push one entry at a time to the output.
   * The order of the keys is not defined, but we assume they are distinct -- don't call {@code put} more than once
   * for the same key.
   */
  interface EntryWriter {

    /**
     * Writes a key value into the map
     *
     * @param k The key
     * @param v The value can be any supported object
     */
    EntryWriter put(CharSequence k, Object v) throws IOException;
    default EntryWriter putNoEx(CharSequence k, Object v) {
      try {
        put(k,v);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
      return this;
    }

    default EntryWriter put(CharSequence k, Object v, BiPredicate<CharSequence, Object> p) throws IOException {
      if (p.test(k,v)) put(k, v);
      return this;
    }

    default EntryWriter putIfNotNull(CharSequence k, Object v) throws IOException {
      if(v != null) put(k,v);
      return this;
    }

    default EntryWriter putStringIfNotNull(CharSequence k, Object v) throws IOException {
      if(v != null) put(k,String.valueOf(v));
      return this;
    }


    default EntryWriter put(CharSequence k, int v) throws IOException {
      put(k, (Integer) v);
      return this;
    }


    default EntryWriter put(CharSequence k, long v) throws IOException {
      put(k, (Long) v);
      return this;
    }


    default EntryWriter put(CharSequence k, float v) throws IOException {
      put(k, (Float) v);
      return this;
    }

    default EntryWriter put(CharSequence k, double v) throws IOException {
      put(k, (Double) v);
      return this;
    }

    default EntryWriter put(CharSequence k, boolean v) throws IOException {
      put(k, (Boolean) v);
      return this;
    }

    /**This is an optimization to avoid the instanceof checks.
     *
     */
    default EntryWriter put(CharSequence k, CharSequence v) throws IOException {
      put(k, (Object)v);
      return this;

    }

    default BiConsumer<CharSequence, Object> getBiConsumer(){
      return (k, v) -> putNoEx(k,v);
    }
  }
  MapWriter EMPTY = ew -> { };
}
