/* UtilLib - Copyright (c) 2011-2017 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.request;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;


/**
 *
 * @author Vincent Calame
 */
public class AppendableRequestMap implements RequestMap {

    private final RequestMap requestMap;
    private final Set<String> parameterNameSet = new HashSet<String>();
    private final Map<String, Object> parameterMap = new HashMap<String, Object>();

    public AppendableRequestMap(RequestMap requestMap) {
        this.requestMap = requestMap;
        parameterNameSet.addAll(requestMap.getParameterNameSet());
    }

    @Override
    public FileValue getFileValue(String name) {
        return requestMap.getFileValue(name);
    }

    @Override
    public FileValue[] getFileValues(String name) {
        return requestMap.getFileValues(name);
    }

    @Override
    public String getParameter(String name) {
        Object obj = parameterMap.get(name);
        if (obj != null) {
            if (obj instanceof String) {
                return (String) obj;
            } else if (obj instanceof String[]) {
                String[] array = (String[]) obj;
                return array[0];
            }
        }
        return requestMap.getParameter(name);
    }

    @Override
    public String[] getParameterValues(String name) {
        Object obj = parameterMap.get(name);
        if (obj != null) {
            if (obj instanceof String) {
                String[] result = new String[1];
                result[0] = (String) obj;
                return result;
            } else if (obj instanceof String[]) {
                return (String[]) obj;
            }
        }
        return requestMap.getParameterValues(name);
    }

    @Override
    public Set<String> getParameterNameSet() {
        return parameterNameSet;
    }

    @Override
    public Locale[] getAcceptableLocaleArray() {
        return requestMap.getAcceptableLocaleArray();
    }

    @Override
    public Object getSourceObject() {
        return requestMap.getSourceObject();
    }

    public void addSupplementaryParameters(Collection<SupplementaryParameter> supplementaryParameters) {
        for (SupplementaryParameter supplementaryParameter : supplementaryParameters) {
            addSupplementaryParameter(supplementaryParameter);
        }
    }

    public void addSupplementaryParameter(SupplementaryParameter supplementaryParameter) {
        boolean isArray = supplementaryParameter.isArray();
        String name = supplementaryParameter.getName();
        if (supplementaryParameter.appendToExisting()) {
            if (isArray) {
                appendParameterValues(name, supplementaryParameter.getValueArray());
            } else {
                appendParameter(name, supplementaryParameter.getValue());
            }
        } else {
            if (isArray) {
                setParameterValues(name, supplementaryParameter.getValueArray());
            } else {
                setParameter(name, supplementaryParameter.getValue());
            }
        }
    }

    public void appendParameter(String paramName, String paramValue) {
        if (paramName == null) {
            throw new IllegalArgumentException("paramName is null");
        }
        if (paramValue == null) {
            throw new IllegalArgumentException("paramValue is null");
        }
        if (!parameterNameSet.contains(paramName)) {
            setParameter(paramName, paramValue);
        } else {
            String[] valueArray = getParameterValues(paramName);
            int length = valueArray.length;
            String[] newArray = new String[length + 1];
            System.arraycopy(valueArray, 0, newArray, 0, length);
            newArray[length] = paramValue;
            parameterMap.put(paramName, newArray);
        }
    }

    public void appendParameterValues(String paramName, String[] paramValues) {
        if (paramName == null) {
            throw new IllegalArgumentException("paramName is null");
        }
        if (paramValues == null) {
            throw new IllegalArgumentException("paramValues is null");
        }
        if (!parameterNameSet.contains(paramName)) {
            setParameterValues(paramName, paramValues);
        } else {
            String[] valueArray = getParameterValues(paramName);
            int length1 = valueArray.length;
            int length2 = paramValues.length;
            String[] newArray = new String[length1 + length2];
            System.arraycopy(valueArray, 0, newArray, 0, length1);
            System.arraycopy(valueArray, 0, newArray, length1, length2);
            parameterMap.put(paramName, newArray);
        }
    }

    public void setParameter(String paramName, String paramValue) {
        if (paramName == null) {
            throw new IllegalArgumentException("paramName is null");
        }
        if (paramValue == null) {
            throw new IllegalArgumentException("paramValue is null");
        }
        parameterNameSet.add(paramName);
        parameterMap.put(paramName, paramValue);
    }

    public void setParameterValues(String paramName, String[] paramValues) {
        if (paramName == null) {
            throw new IllegalArgumentException("paramName is null");
        }
        if (paramValues == null) {
            throw new IllegalArgumentException("paramValues is null");
        }
        parameterNameSet.add(paramName);
        parameterMap.put(paramName, paramValues);
    }


}
