/*
 * 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.felix.dm.runtime;

import java.lang.reflect.Array;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * This class represents the parsed data found from meta-inf dependencymanager descriptors.
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class JSONMetaData implements MetaData, Cloneable
{
    /**
     * The parsed Dependency or Service metadata. The map value is either a String, a String[],
     * or a Dictionary, whose values are String or String[]. 
     */
    private HashMap<String, Object> m_metadata = new HashMap<String, Object>();

    /**
     * Decodes Json metadata for either a Service or a Dependency descriptor entry.
     * The JSON object has the following form:
     * 
     * entry            ::= String | String[] | dictionary
     * dictionary       ::= key-value-pair*
     * key-value-pair   ::= key value
     * value            ::= String | String[] | value-type
     * value-type       ::= jsonObject with value-type-info
     * value-type-info  ::= "type"=primitive java type
     *                      "value"=String|String[]
     *                      
     * Exemple:
     * 
     * {"string-param" : "string-value",
     *  "string-array-param" : ["string1", "string2"],
     *  "properties" : {
     *      "string-param" : "string-value",
     *      "string-array-param" : ["str1", "str2],
     *      "long-param" : {"type":"java.lang.Long", "value":"1"}}
     *      "long-array-param" : {"type":"java.lang.Long", "value":["1"]}}
     *  }
     * }
     *   
     * @param input the JSON string that corresponds to a dependency manager descriptor entry line.
     * @throws Exception 
     */
    @SuppressWarnings("unchecked")
    public JSONMetaData(String input) throws Exception
    {
    	JsonReader jreader = new JsonReader(input);
        Map<String, Object> m = jreader.getParsed();
        
        for (Map.Entry<String, Object> e : m.entrySet())
        {
        	String key = e.getKey();
        	Object value = e.getValue();
        	if (value instanceof String)
        	{
                m_metadata.put(key, value);
        	} else if (value instanceof List)
        	{
        		// String array
                m_metadata.put(key, decodeStringArray((List<?>) value));
        	} else if (value instanceof Map)
        	{
        		// properties
                m_metadata.put(key, parseProperties((Map<String, Object>) value));
        	}
        }
    }

    @SuppressWarnings("unchecked")
	private Hashtable<String, Object> parseProperties(Map<String, Object> properties) throws Exception {
        Hashtable<String, Object> parsedProps = new Hashtable<String, Object>();
        
        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            String key = entry.getKey();            
            Object value = entry.getValue();
            
            if (value instanceof String)
            {
                // This property type is a simple string
            	parsedProps.put(key, value);
            }
            else if (value instanceof List)
            {
                // This property type is a simple string array
                parsedProps.put(key, decodeStringArray((List<?>) value));
            }
            else if (value instanceof Map)
            {
                // This property type is a typed value, encoded as a JSONObject with two keys: "type"/"value"
                Map<String, Object> json = ((Map<String, Object>) value);
                String type = json.get("type").toString();
                Object typeValue = json.get("value");

                if (type == null)
                {
                    throw new Exception("missing type attribute in json metadata for key " + key);
                }
                if (typeValue == null)
                {
                    throw new Exception("missing type value attribute in json metadata for key " + key);
                }

                Class<?> typeClass;
                try
                {
                    typeClass = Class.forName(type);
                }
                catch (ClassNotFoundException e)
                {
                    throw new Exception("invalid type attribute (" + type + ") in json metadata for key "
                        + key);
                }

                if (typeValue instanceof List)
                {
                    parsedProps.put(key, toPrimitiveTypeArray(typeClass, (List<?>) typeValue));
                }
                else 
                {
                    parsedProps.put(key, toPrimitiveType(typeClass, typeValue.toString()));
                }
            }
        }
        
        return parsedProps;
    }

    private Object toPrimitiveType(Class<?> type, String value) throws Exception {
        if (type.equals(String.class))
        {
            return value;
        }
        else if (type.equals(Long.class))
        {
            return Long.parseLong(value);
        }
        else if (type.equals(Double.class))
        {
            return Double.valueOf(value);
        }
        else if (type.equals(Float.class))
        {
            return Float.valueOf(value);
        }
        else if (type.equals(Integer.class))
        {
            return Integer.valueOf(value);
        }
        else if (type.equals(Byte.class))
        {
            return Byte.valueOf(value);
        }
        else if (type.equals(Character.class))
        {
            try {
                return Character.valueOf((char) Integer.parseInt(value));
            } catch (NumberFormatException e) {
                return value.charAt(0);
            }
        }
        else if (type.equals(Boolean.class))
        {
            return Boolean.valueOf(value);
        }
        else if (type.equals(Short.class))
        {
            return Short.valueOf(value);
        }
        else
        {
            throw new Exception("invalid type (" + type + ") attribute in json metadata");
        }
    }

    private Object toPrimitiveTypeArray(Class<?> type, List<?> array) throws Exception {
        int len = array.size();
        Object result = Array.newInstance(type, len);

        if (type.equals(String.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, array.get(i).toString());
            }
        } 
        else if (type.equals(Long.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Long.valueOf(array.get(i).toString()));
            }
        }
        else if (type.equals(Double.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Double.valueOf(array.get(i).toString()));
            }
        } 
        else if (type.equals(Float.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Float.valueOf(array.get(i).toString()));
            }
        }
        else if (type.equals(Integer.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Integer.valueOf(array.get(i).toString()));
            }
        }
        else if (type.equals(Byte.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Byte.valueOf(array.get(i).toString()));
            }
        }
        else if (type.equals(Character.class))
        {
            for (int i = 0; i < len; i ++) {
                try {
                    Array.set(result, i,  Character.valueOf((char) Integer.parseInt(array.get(i).toString())));
                } catch (NumberFormatException e) {
                    Array.set(result, i,  Character.valueOf((char) array.get(i).toString().charAt(0)));  
                }
            }
        }
        else if (type.equals(Boolean.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Boolean.valueOf(array.get(i).toString()));
            }
        } 
        else if (type.equals(Short.class))
        {
            for (int i = 0; i < len; i ++) {
                Array.set(result, i, Short.valueOf(array.get(i).toString()));
            }
        }
        else 
        {
            throw new Exception("invalid type (" + type + ") attribute in json metadata");
        }   
        return result;
    }

    /**
     * Close this class instance to another one.
     */
    @SuppressWarnings("unchecked")
    @Override
    public Object clone() throws CloneNotSupportedException
    {
        JSONMetaData clone = (JSONMetaData) super.clone();
        clone.m_metadata = (HashMap<String, Object>) m_metadata.clone();
        return clone;
    }
    
    public String getString(Params key)
    {
        Object value = m_metadata.get(key.toString());
        if (value == null)
        {
            throw new IllegalArgumentException("Parameter " + key + " not found");
        }
        return value.toString();
    }

    public String getString(Params key, String def)
    {
        try
        {
            return getString(key);
        }
        catch (IllegalArgumentException e)
        {
            return def;
        }
    }

    public int getInt(Params key)
    {
        Object value = m_metadata.get(key.toString());
        if (value != null)
        {
            try
            {
                if (value instanceof Integer) {
                    return ((Integer) value).intValue();
                }
                return Integer.parseInt(value.toString());
            }
            catch (NumberFormatException e)
            {
                throw new IllegalArgumentException("parameter " + key
                    + " is not an int value: "
                    + value);
            }
        }
        else
        {
            throw new IllegalArgumentException("missing " + key
                + " parameter from annotation");
        }
    }

    public int getInt(Params key, int def)
    {
        Object value = m_metadata.get(key.toString());
        if (value != null)
        {
            try
            {
                if (value instanceof Integer) {
                    return ((Integer) value).intValue();
                }
                return Integer.parseInt(value.toString());
            }
            catch (NumberFormatException e)
            {
                throw new IllegalArgumentException("parameter " + key
                    + " is not an int value: "
                    + value);
            }
        }
        else
        {
            return def;
        }
    }

    public long getLong(Params key)
    {
        Object value = m_metadata.get(key.toString());
        if (value != null)
        {
            try
            {
                if (value instanceof Long) {
                    return ((Long) value).longValue();
                }
                return Long.parseLong(value.toString());
            }
            catch (NumberFormatException e)
            {
                throw new IllegalArgumentException("parameter " + key
                    + " is not a long value: "
                    + value);
            }
        }
        else
        {
            throw new IllegalArgumentException("missing " + key
                + " parameter from annotation");
        }
    }

    public long getLong(Params key, long def)
    {
        Object value = m_metadata.get(key.toString());
        if (value != null)
        {
            try
            {
                if (value instanceof Long) {
                    return (Long) value;
                }
                return Long.parseLong(value.toString());
            }
            catch (NumberFormatException e)
            {
                throw new IllegalArgumentException("parameter " + key
                    + " is not a long value: "
                    + value);
            }
        }
        else
        {
            return def;
        }
    }

    public String[] getStrings(Params key)
    {
        Object array = m_metadata.get(key.toString());
        if (array == null)
        {
            throw new IllegalArgumentException("Parameter " + key + " not found");
        }

        if (!(array instanceof String[]))
        {
            throw new IllegalArgumentException("Parameter " + key + " is not a String[] (" + array.getClass()
                + ")");
        }
        return (String[]) array;
    }

    public String[] getStrings(Params key, String[] def)
    {
        try
        {
            return getStrings(key);
        }
        catch (IllegalArgumentException t)
        {
            return def;
        }
    }

    @SuppressWarnings("unchecked")
    public Dictionary<String, Object> getDictionary(Params key,
        Dictionary<String, Object> def)
    {
        Object dictionary = m_metadata.get(key.toString());
        if (dictionary == null)
        {
            return def;
        }

        if (!(dictionary instanceof Dictionary<?, ?>))
        {
            throw new IllegalArgumentException("Parameter " + key + " is not a Dictionary ("
                + dictionary.getClass() + ")");
        }

        return (Dictionary<String, Object>) dictionary;
    }

    @Override
    public String toString()
    {
        return m_metadata.toString();
    }

    public void setDictionary(Params key, Dictionary<String, Object> dictionary)
    {
        m_metadata.put(key.toString(), dictionary);
    }

    public void setString(Params key, String value)
    {
        m_metadata.put(key.toString(), value);
    }

    public void setStrings(Params key, String[] values)
    {
        m_metadata.put(key.toString(), values);
    }
    
    /**
     * Decodes a JSONArray into a String array (all JSON array values are supposed to be strings).
     */
    private String[] decodeStringArray(List<?> array)
    {
    	return array.stream().map(x -> x.toString()).toArray(String[]::new);
    }
}
