package ru.yandex.autotests.directapi.matchers.beans.version5;

import javax.xml.bind.JAXBElement;

import ru.yandex.autotests.irt.testutils.beandiffer.diff.Diff;
import ru.yandex.autotests.irt.testutils.beandiffer.differ.BeanDiffer;
import ru.yandex.autotests.irt.testutils.beandiffer.differ.Differ;
import ru.yandex.autotests.irt.testutils.beandiffer.differ.EnumDiffer;
import ru.yandex.autotests.irt.testutils.beandiffer.differ.SimpleTypeDiffer;


/**
 * Created by chicos on 04.12.2014.
 */
public class JAXBElementDiffer<T> extends Differ<T> {

    @Override
    public boolean accepts(Class type) {
        return JAXBElement.class.isAssignableFrom(type);
    }

    @Override
    public Diff compare(T expected, T actual) {
        Class valueType = ((JAXBElement) expected).getDeclaredType();
        if (isSimpleType(valueType)) {
            return new SimpleTypeDiffer<>()
                    .compare(
                            ((JAXBElement) expected).getValue(),
                            ((JAXBElement) actual).getValue());
        } else if (valueType.isEnum()) {
            return new EnumDiffer<>()
                    .withFieldPath(fieldPath)
                    .compare(
                            (Enum) ((JAXBElement) expected).getValue(),
                            (Enum) ((JAXBElement) actual).getValue());
        } else {
            return new BeanDiffer()
                    .withFieldPath(fieldPath)
                    .compare(
                            ((JAXBElement) expected).getValue(),
                            ((JAXBElement) actual).getValue());
        }
    }

    private boolean isSimpleType(Class valueType) {
        return (valueType.isPrimitive() ||
                Number.class.isAssignableFrom(valueType) ||
                valueType.equals(Boolean.class) ||
                valueType.equals(String.class) ||
                valueType.equals(Class.class));
    }
}
