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

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.felix.schematizer.Node;
import org.apache.felix.schematizer.Schema;
import org.osgi.dto.DTO;
import org.osgi.util.converter.ConversionException;
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;

import static org.apache.felix.schematizer.impl.Util.asDTO;
import static org.apache.felix.schematizer.impl.Util.rawClassOf;

public class SchemaBasedConverter<T> implements TargetRule {
    private final SchemaImpl schema;
    private final Converter converter;

    public SchemaBasedConverter(SchemaImpl aSchema) {
        schema = aSchema;
        converter = Converters.standardConverter();
        // TODO: how can we add the error handler??
//                .newConverterBuilder()
//                .errorHandler( (obj,type) -> new Exception( "Could not convert object " + obj.toString() + " of type " + type.getTypeName() ) )
//                .build();
    }

    @Override
    public ConverterFunction getFunction() {
        return (obj,t) -> {
            if (!(obj instanceof Map) || schema == null)
                return handleInvalid();
            return convertMap((Map<?,?>)obj, schema, "/");
        };
    }

    @Override
    public Type getTargetType() {
        return schema.rootNode().type();
    }

    @SuppressWarnings( "unchecked" )
    private T convertMap(Map<?,?> map, Schema s, String contextPath) {
        Node node = s.nodeAtPath(contextPath);
        Class<?> cls = Util.rawClassOf(node.type());

        if (!asDTO(cls))
            return handleInvalid();

        if (!contextPath.endsWith("/"))
            contextPath = contextPath + "/";

        return (T)convertToDTO((Class<? extends DTO>)cls, map, s, contextPath);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private <U extends DTO>U convertToDTO(Class<U> targetCls, Map<?,?> m, Schema schema, String contextPath) {
        try {
            U dto;

            try {
                dto = targetCls.newInstance();
            } catch (Throwable t) {
                throw new ConversionException("Cannot create instance of DTO " + targetCls + ". Bad constructor?", t);
            }

            for (Map.Entry entry : m.entrySet()) {
                try {
                    Field f = targetCls.getField(entry.getKey().toString());
                    Object val = entry.getValue();
                    if (val == null)
                        continue;
                    String path = contextPath + f.getName();
                    Node node = schema.nodeAtPath(path);
                    Object obj;
                    if (node.typeReference().isPresent()) {
                        TypeReference<?> tr = Util.typeReferenceOf(node.typeReference().get());
                        if (node.isCollection())
                            if (!Collection.class.isAssignableFrom(val.getClass()))
                                // TODO: PANIC! Something is wrong... what should we do??
                                obj = null;
                            else
                                obj = convertToCollection( (Class)Util.rawClassOf(tr), (Class)node.collectionType(), (Collection)val, schema, path);
                        else
                            obj = convertToDTO((Class<? extends DTO>)rawClassOf(tr), (Map<?,?>)val, schema, path + "/");
                    } else {
                        if (node.isCollection()) {
                            Collection c = instantiateCollection(node.collectionType());
                            Type type = node.type();
                            for (Object o : (Collection)val) {
                                if (o == null)
                                    c.add(null);
                                else if (asDTO(rawClassOf(type)))
                                    c.add(convertToDTO((Class)Util.rawClassOf(type), (Map)o, schema, path + "/"));
                                else
                                    c.add(converter.convert(o).to(type));
                            }
                            obj = c;
                        } else {
                            Class<?> rawClass = rawClassOf(node.type());
                            if (asDTO(rawClass))
                                obj = convertToDTO((Class<? extends DTO>)rawClass, (Map<?,?>)val, schema, path + "/");
                            else
                                obj = converter.convert(val).to(node.type());
                        }
                    }

                    f.set(dto, obj);
                } catch (NoSuchFieldException e) {
                }
            }

            return dto;
        } catch (Exception e) {
            throw new ConversionException("Cannot create DTO " + targetCls, e);
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private <U, V extends Collection<U>>V convertToCollection(Class<U> targetCls, Class<V> collectionClass, Collection sourceCollection, Schema schema, String path) {
        try {
            V targetCollection = instantiateCollection(collectionClass);
            sourceCollection.stream()
                .map(obj -> convertCollectionItemToObject(obj, targetCls, schema, path))
                .forEach(u -> targetCollection.add((U)u));

            return targetCollection;
        } catch (Exception e) {
            throw new ConversionException("Cannot create DTO " + targetCls, e);
        }
    }

    @SuppressWarnings( "unchecked" )
    private <V extends Collection<?>>V instantiateCollection(Class<V> collectionClass) {
        if (collectionClass == null)
            return (V)new ArrayList<V>();
        if (Collection.class.equals(collectionClass) || List.class.isAssignableFrom(collectionClass))
            return (V)new ArrayList<V>();
        else
            // TODO: incomplete
            return null;
    }

    private <U>U convertCollectionItemToObject(Object obj, Class<U> targetCls, Schema schema, String path) {
        try
        {
            if (asDTO(targetCls))
                return convertCollectionItemToDTO(obj, targetCls, schema, path);

            U newItem = targetCls.newInstance();
            return newItem;
        }
        catch ( Exception e )
        {
            e.printStackTrace();
            return null;
        }
    }

    @SuppressWarnings( "unchecked" )
    private <U>U convertCollectionItemToDTO(Object obj, Class<U> targetCls, Schema schema, String path) {
        Node node = schema.nodeAtPath(path);
        if (node.typeReference().isPresent()) {
            TypeReference<U> tr = (TypeReference<U>)Util.typeReferenceOf(node.typeReference().get());
            return converter.convert(obj).to(tr);
        } else {
            Type type = node.type();
            type.toString();
            // TODO
//            if (DTO.class.isAssignableFrom(Util.rawClassOf(type)))
//                obj = convertToDTO((Class)Util.rawClassOf(type), (Map)val, schema, path + "/" );
//            else
//                obj = converter.convert(val).to(type);
            return null;
        }
    }

    // TODO
    private T handleInvalid() {
        return null;
    }
}
