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

import java.io.IOException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


/**
 * This class is similar to MultiMapSolrParams except you can edit the 
 * parameters after it is initialized.  It has helper functions to set/add
 * integer and boolean param values.
 * 
 * @since solr 1.3
 */
public class ModifiableSolrParams extends SolrParams 
{
  private Map<String,String[]> vals;
  
  public ModifiableSolrParams()
  {
    // LinkedHashMap so params show up in CGI in the same order as they are entered
    vals = new LinkedHashMap<>();
  }

  /** Constructs a new ModifiableSolrParams directly using the provided Map&lt;String,String[]&gt; */
  public ModifiableSolrParams( Map<String,String[]> v )
  {
    vals = v;
  }

  /** Constructs a new ModifiableSolrParams, copying values from an existing SolrParams */
  public ModifiableSolrParams(SolrParams params)
  {
    vals = new LinkedHashMap<>();
    if( params != null ) {
      this.add( params );
    }
  }

  //----------------------------------------------------------------
  //----------------------------------------------------------------

  /**
   * Replace any existing parameter with the given name.  if val==null remove key from params completely.
   */
  public ModifiableSolrParams set( String name, String ... val ) {
    if (val==null || (val.length==1 && val[0]==null)) {
      vals.remove(name);
    } else {
      vals.put( name, val );
    }
    return this;
  }
  
  public ModifiableSolrParams set( String name, int val ) {
    set( name, String.valueOf(val) );
    return this;
  }
  
  public ModifiableSolrParams set( String name, boolean val ) {
    set( name, String.valueOf(val) );
    return this;
  }

  /**
   * Add the given values to any existing name
   * @param name Key
   * @param val Array of value(s) added to the name. NOTE: If val is null 
   *     or a member of val is null, then a corresponding null reference 
   *     will be included when a get method is called on the key later.
   *  @return this
   */
  public ModifiableSolrParams add( String name, String ... val ) {
    String[] old = vals.put(name, val);
    if( old != null ) {
      if( val == null || val.length < 1 ) {
        String[] both = new String[old.length+1];
        System.arraycopy(old, 0, both, 0, old.length);
        both[old.length] = null;
        vals.put( name, both );
      }
      else {
        String[] both = new String[old.length+val.length];
        System.arraycopy(old, 0, both, 0, old.length);
        System.arraycopy(val, 0, both, old.length, val.length);
        vals.put( name, both );
      }
    }
    return this;
  }

  public void add(SolrParams params)
  {
    Iterator<String> names = params.getParameterNamesIterator();
    while (names.hasNext()) {
      String name = names.next();
      set(name, params.getParams(name));
    }
  }
  
  /**
   * remove a field at the given name
   */
  public String[] remove( String name )
  {
    return vals.remove( name );
  }
  
  /** clear all parameters */
  public void clear()
  {
    vals.clear();
  }
  
  /** 
   * remove the given value for the given name
   * 
   * @return true if the item was removed, false if null or not present
   */
  public boolean remove(String name, String value) {
     String[] tmp = vals.get(name);
     if (tmp==null) return false;
     for (int i=0; i<tmp.length; i++) {
       if (tmp[i].equals(value)) {
         String[] tmp2 = new String[tmp.length-1];
         if (tmp2.length==0) {
           tmp2 = null;
           remove(name);
         } else {
           System.arraycopy(tmp, 0, tmp2, 0, i);
           System.arraycopy(tmp, i+1, tmp2, i, tmp.length-i-1);
           set(name, tmp2);
         }
         return true;
       }
     }
     return false;
  }

  //----------------------------------------------------------------
  //----------------------------------------------------------------

  @Override
  public String get(String param) {
    String[] v = vals.get( param );
    if( v!= null && v.length > 0 ) {
      return v[0];
    }
    return null;
  }

  @Override
  public Iterator<String> getParameterNamesIterator() {
    return vals.keySet().iterator();
  }
  
  public Set<String> getParameterNames() {
    return vals.keySet();
  }

  @Override
  public String[] getParams(String param) {
    return vals.get( param );
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(128);
    try {
      boolean first=true;

      for (Map.Entry<String,String[]> entry : vals.entrySet()) {
        String key = entry.getKey();
        String[] valarr = entry.getValue();
        for (String val : valarr) {
          if (!first) sb.append('&');
          first=false;
          sb.append(key);
          sb.append('=');
          if( val != null ) {
            sb.append( URLEncoder.encode( val, "UTF-8" ) );
          }
        }
      }
    }
    catch (IOException e) {throw new RuntimeException(e);}  // can't happen

    return sb.toString();
  }
}
