package it.integry.integrywmsnative.core.utility;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class UtilityReflections {


    public static void copy(Object from, Object to) throws Exception {
        UtilityReflections.copy(from, to, Object.class);
    }

    public static void copy(Object from, Object to, Class depth) throws Exception {
        Class fromClass = from.getClass();
        Class toClass = to.getClass();
        List<Field> fromFields = collectFields(fromClass, depth);
        List<Field> toFields = collectFields(toClass, depth);
        Field target;
        for (Field source : fromFields) {
            if ((target = findAndRemove(source, toFields)) != null) {
                source.setAccessible(true);
                target.setAccessible(true);
                target.set(to, source.get(from));
            }
        }
    }

    private static List<Field> collectFields(Class c, Class depth) {
        List<Field> accessibleFields = new ArrayList<>();
        do {
            int modifiers;
            for (Field field : c.getDeclaredFields()) {
                modifiers = field.getModifiers();
                if (!Modifier.isStatic(modifiers)/* && Modifier.isPublic(modifiers)*/) {
                    accessibleFields.add(field);
                }
            }
            c = c.getSuperclass();
        } while (c != null && c != depth);
        return accessibleFields;
    }

    private static Field findAndRemove(Field field, List<Field> fields) {
        Field actual;
        for (Iterator<Field> i = fields.iterator(); i.hasNext();) {
            actual = i.next();
            if (field.getName().equals(actual.getName())
                    && field.getType().equals(actual.getType())) {
                i.remove();
                return actual;
            }
        }
        return null;
    }


}
