/*
 * 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.configurator.impl.json;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonStructure;

import org.osgi.util.converter.Converter;
import org.osgi.util.converter.ConverterFunction;
import org.osgi.util.converter.Converters;
import org.osgi.util.converter.TargetRule;
import org.osgi.util.converter.TypeReference;

public class TypeConverter {

    public static Converter getConverter() {
        return Converters.standardConverter().newConverterBuilder().rule(new TargetRule() {

            @Override
            public Type getTargetType() {
                return String.class;
            }

            @Override
            public ConverterFunction getFunction() {
                return new ConverterFunction() {

                    @Override
                    public Object apply(final Object obj, final Type targetType) throws Exception {
                        if ( obj instanceof Map || obj instanceof List ) {
                            final JsonStructure json = JSONUtil.build(obj);
                            final StringWriter w = new StringWriter();
                            Json.createWriter(w).write(json);
                            return w.toString();
                        }
                        return CANNOT_HANDLE;
                    }
                };
            }
        }).build();
    }

    private static final Map<String, Class<?>> TYPE_MAP = new HashMap<>();
    static {
        // scalar types and primitive types
        TYPE_MAP.put("String", String.class);
        TYPE_MAP.put("Integer", Integer.class);
        TYPE_MAP.put("int", Integer.class);
        TYPE_MAP.put("Long", Long.class);
        TYPE_MAP.put("long", Long.class);
        TYPE_MAP.put("Float", Float.class);
        TYPE_MAP.put("float", Float.class);
        TYPE_MAP.put("Double", Double.class);
        TYPE_MAP.put("double", Double.class);
        TYPE_MAP.put("Byte", Byte.class);
        TYPE_MAP.put("byte", Byte.class);
        TYPE_MAP.put("Short", Short.class);
        TYPE_MAP.put("short", Short.class);
        TYPE_MAP.put("Character", Character.class);
        TYPE_MAP.put("char", Character.class);
        TYPE_MAP.put("Boolean", Boolean.class);
        TYPE_MAP.put("boolean", Boolean.class);
         // array of scalar types and primitive types
        TYPE_MAP.put("String[]", String[].class);
        TYPE_MAP.put("Integer[]", Integer[].class);
        TYPE_MAP.put("int[]", int[].class);
        TYPE_MAP.put("Long[]", Long[].class);
        TYPE_MAP.put("long[]", long[].class);
        TYPE_MAP.put("Float[]", Float[].class);
        TYPE_MAP.put("float[]", float[].class);
        TYPE_MAP.put("Double[]", Double[].class);
        TYPE_MAP.put("double[]", double[].class);
        TYPE_MAP.put("Byte[]", Byte[].class);
        TYPE_MAP.put("byte[]", byte[].class);
        TYPE_MAP.put("Short[]", Short[].class);
        TYPE_MAP.put("short[]", short[].class);
        TYPE_MAP.put("Boolean[]", Boolean[].class);
        TYPE_MAP.put("boolean[]", boolean[].class);
        TYPE_MAP.put("Character[]", Character[].class);
        TYPE_MAP.put("char[]", char[].class);
    }

    private final List<File> allFiles = new ArrayList<>();

    private final List<File> files = new ArrayList<>();

    private final BinUtil.ResourceProvider provider;

    /**
     * Create a new instance
     * @param provider The bundle provider, might be {@code null}.
     */
    public TypeConverter(final BinUtil.ResourceProvider provider) {
        this.provider = provider;
    }

    /**
     * Convert a value to the given type
     * @param value The value
     * @param typeInfo Optional type info, might be {@code null}
     * @return The converted value or {@code null} if the conversion failed.
     * @throws IOException If an error happens
     */
    public Object convert(
            final String pid,
            final Object value,
            final String typeInfo) throws IOException {
        if ( typeInfo == null ) {
            if ( value instanceof String || value instanceof Boolean ) {
                return value;
            } else if ( value instanceof Long || value instanceof Double ) {
                return value;
            } else if ( value instanceof Integer ) {
                return ((Integer)value).longValue();
            } else if ( value instanceof Short ) {
                return ((Short)value).longValue();
            } else if ( value instanceof Byte ) {
                return ((Byte)value).longValue();
            } else if ( value instanceof Float ) {
                return ((Float)value).doubleValue();
            }
            if ( value instanceof List ) {
                @SuppressWarnings("unchecked")
                final List<Object> list = (List<Object>)value;
                if ( list.isEmpty() ) {
                    return new String[0];
                }
                final Object firstObject = list.get(0);
                boolean hasListOrMap = false;
                for(final Object v : list) {
                    if ( v instanceof List || v instanceof Map ) {
                        hasListOrMap = true;
                        break;
                    }
                }
                Object convertedValue = null;
                if ( !hasListOrMap ) {
                    if ( firstObject instanceof Boolean ) {
                        convertedValue = getConverter().convert(list).defaultValue(null).to(Boolean[].class);
                    } else if ( firstObject instanceof Long || firstObject instanceof Integer || firstObject instanceof Byte || firstObject instanceof Short ) {
                        convertedValue =  getConverter().convert(list).defaultValue(null).to(Long[].class);
                    } else if ( firstObject instanceof Double || firstObject instanceof Float ) {
                        convertedValue =  getConverter().convert(list).defaultValue(null).to(Double[].class);
                    }
                }
                if ( convertedValue == null ) {
                    convertedValue = getConverter().convert(list).defaultValue(null).to(String[].class);
                }
                return convertedValue;
            }
            return null;
        }

        // binary
        if ( "binary".equals(typeInfo) ) {
            if ( provider == null ) {
                throw new IOException("Binary files only allowed within a bundle");
            }
            final String path = getConverter().convert(value).defaultValue(null).to(String.class);
            if ( path == null ) {
                throw new IOException("Invalid path for binary property: " + value);
            }
            final File filePath;
            try {
                filePath = BinUtil.extractFile(provider, pid, path);
            } catch ( final IOException ioe ) {
                throw new IOException("Unable to read " + path +
                        " in bundle " + provider.getIdentifier() +
                        " for pid " + pid +
                        " and write to " + BinUtil.binDirectory + " : " + ioe.getMessage(), ioe);
            }
            if ( filePath == null ) {
                throw new IOException("Entry " + path + " not found in bundle " + provider.getIdentifier());
            }
            files.add(filePath);
            allFiles.add(filePath);
            return filePath.getAbsolutePath();

        } else if ( "binary[]".equals(typeInfo) ) {
            if ( provider == null ) {
                throw new IOException("Binary files only allowed within a bundle");
            }
            final String[] paths = getConverter().convert(value).defaultValue(null).to(String[].class);
            if ( paths == null ) {
                throw new IOException("Invalid paths for binary[] property: " + value);
            }
            final String[] filePaths = new String[paths.length];
            int i = 0;
            while ( i < paths.length ) {
                final File filePath;
                try {
                    filePath = BinUtil.extractFile(provider, pid, paths[i]);
                } catch ( final IOException ioe ) {
                    throw new IOException("Unable to read " + paths[i] +
                            " in bundle " + provider.getIdentifier() +
                            " for pid " + pid +
                            " and write to " + BinUtil.binDirectory + " : " + ioe.getMessage(), ioe);
                }
                if ( filePath == null ) {
                    throw new IOException("Entry " + paths[i] + " not found in bundle " + provider.getIdentifier());
                }
                files.add(filePath);
                allFiles.add(filePath);
                filePaths[i] = filePath.getAbsolutePath();
                i++;
            }
            return filePaths;
        }

        final Class<?> typeClass = TYPE_MAP.get(typeInfo);
        if ( typeClass != null ) {
            return getConverter().convert(value).defaultValue(null).to(typeClass);
        }

        // Collections of scalar types
        if ( "Collection<String>".equals(typeInfo) ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<String>>() {});

        } else if ( "Collection<Integer>".equals(typeInfo) ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Integer>>() {});

        } else if ( "Collection<Long>".equals(typeInfo) ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Long>>() {});

        } else if ( "Collection<Float>".equals(typeInfo)  ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Float>>() {});

        } else if ( "Collection<Double>".equals(typeInfo)  ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Double>>() {});

        } else if ( "Collection<Byte>".equals(typeInfo) ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Byte>>() {});

        } else if ( "Collection<Short>".equals(typeInfo)  ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Short>>() {});

        } else if ( "Collection<Character>".equals(typeInfo) ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Character>>() {});

        } else if ( "Collection<Boolean>".equals(typeInfo) ) {
            return getConverter().convert(value).defaultValue(null).to(new TypeReference<ArrayList<Boolean>>() {});
        } else if ( "Collection".equals(typeInfo) ) {
            if ( value instanceof List ) {
                @SuppressWarnings("unchecked")
                final List<Object> list = (List<Object>)value;
                if ( list.isEmpty() ) {
                    return Collections.EMPTY_LIST;
                }
                final Object firstObject = list.get(0);
                boolean hasListOrMap = false;
                for(final Object v : list) {
                    if ( v instanceof List || v instanceof Map ) {
                        hasListOrMap = true;
                        break;
                    }
                }
                Object convertedValue = null;
                if ( !hasListOrMap ) {
                    if ( firstObject instanceof Boolean ) {
                        convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<ArrayList<Boolean>>() {});
                    } else if ( firstObject instanceof Long || firstObject instanceof Integer || firstObject instanceof Byte || firstObject instanceof Short) {
                        convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<ArrayList<Long>>() {});
                    } else if ( firstObject instanceof Double || firstObject instanceof Float ) {
                        convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<ArrayList<Double>>() {});
                    }
                }
                if ( convertedValue == null ) {
                    convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<List<String>>() {});
                }
                return convertedValue;
            }
            return getConverter().convert(value).defaultValue(null).to(ArrayList.class);
        }

        // unknown type - ignore configuration
        throw new IOException("Invalid type information: " + typeInfo);
    }

    public void cleanupFiles() {
        for(final File f : allFiles) {
            f.delete();
        }
    }

    public List<File> flushFiles() {
        if ( this.files.isEmpty() ) {
            return null;
        } else {
            final List<File> result = new ArrayList<>(this.files);
            this.files.clear();
            return result;
        }
    }
}
