/*
 * 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.johnzon.mapper.access;

import static org.apache.johnzon.mapper.reflection.Records.isRecord;

import org.apache.johnzon.mapper.Adapter;
import org.apache.johnzon.mapper.JohnzonIgnore;
import org.apache.johnzon.mapper.JohnzonProperty;
import org.apache.johnzon.mapper.ObjectConverter;
import org.apache.johnzon.mapper.util.BeanUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

// annotated entity overrides the other one, methods are used instead of field if both are there
public class FieldAndMethodAccessMode extends BaseAccessMode {
    private final FieldAccessMode fields;
    private final MethodAccessMode methods;
    private final boolean alwaysPreferMethodVisibility;
    private final boolean ignoreVisibilityFilter;

    public FieldAndMethodAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor,
                                    final boolean useGettersAsWriter, final boolean alwaysPreferMethodVisibility,
                                    final boolean ignoreVisibilityFilter) {
        super(useConstructor, acceptHiddenConstructor);
        this.fields = new FieldAccessMode(useConstructor, acceptHiddenConstructor);
        this.methods = new MethodAccessMode(
                useConstructor, acceptHiddenConstructor, useGettersAsWriter);
        this.alwaysPreferMethodVisibility = alwaysPreferMethodVisibility;
        this.ignoreVisibilityFilter = ignoreVisibilityFilter;
    }

    @Deprecated // backward compat
    public FieldAndMethodAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor,
                                    final boolean useGettersAsWriter, final boolean alwaysPreferMethodVisibility) {
        this(useConstructor, acceptHiddenConstructor, useGettersAsWriter, alwaysPreferMethodVisibility, false);
    }

    // backward compatibility, don't delete since it can be used from user code in jsonb delegate access mode property
    @Deprecated
    public FieldAndMethodAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor,
                                    final boolean useGettersAsWriter) {
        this(useConstructor, acceptHiddenConstructor, useGettersAsWriter, true, false);
    }


    @Override
    public Map<String, Reader> doFindReaders(final Class<?> clazz) {
        final Map<String, Reader> methodReaders = this.methods.findReaders(clazz);
        final boolean record = isRecord(clazz);
        if (record) {
            return methodReaders;
        }

        final Map<String, Reader> fieldsReaders = this.fields.findReaders(clazz);
        final Map<String, Reader> readers = new HashMap<>();

        for (final Map.Entry<String, Reader> entry : fieldsReaders.entrySet()) {
            final String key = entry.getKey();
            Method m = record ?
                    getMethod(key, clazz) :
                    getMethod("get" + Character.toUpperCase(key.charAt(0)) + (key.length() > 1 ? key.substring(1) : ""), clazz);
            if (m == null && !record && (boolean.class == entry.getValue().getType() || Boolean.class == entry.getValue().getType())) {
                m = getMethod("is" + Character.toUpperCase(key.charAt(0)) + (key.length() > 1 ? key.substring(1) : ""), clazz);
            }
            boolean skip = false;
            if (m != null && (ignoreVisibilityFilter || Modifier.isPublic(m.getModifiers()))) {
                for (final Reader w : methodReaders.values()) {
                    if (MethodAccessMode.MethodDecoratedType.class.cast(w).getMethod().equals(m)) {
                        if (w.getAnnotation(JohnzonProperty.class) != null || w.getAnnotation(JohnzonIgnore.class) != null) {
                            skip = true;
                        }
                        break;
                    }
                }
            } else if (!ignoreVisibilityFilter && m != null) {
                continue;
            }
            if (skip) {
                continue;
            }
            readers.put(entry.getKey(), entry.getValue());
        }

        for (final Map.Entry<String, Reader> entry : methodReaders.entrySet()) {
            final Method mr = MethodAccessMode.MethodDecoratedType.class.cast(entry.getValue()).getMethod();
            final String fieldName = record ?
                    mr.getName() :
                    BeanUtil.decapitalize(mr.getName().startsWith("is") ?
                            mr.getName().substring(2) : mr.getName().substring(3));
            final Field f = getField(fieldName, clazz);
            boolean skip = false;
            if (f != null) {
                for (final Reader w : fieldsReaders.values()) {
                    if (FieldAccessMode.FieldDecoratedType.class.cast(w).getField().equals(f)) {
                        if (w.getAnnotation(JohnzonProperty.class) != null || w.getAnnotation(JohnzonIgnore.class) != null) {
                            skip = true;
                        }
                        break;
                    }
                }
            }
            if (skip) {
                continue;
            }

            final Reader existing = readers.get(entry.getKey());
            if (existing == null) {
                if (f != null) { // useful to hold the Field and transient state for example, just as fallback
                    readers.put(entry.getKey(), new CompositeReader(
                            entry.getValue(), new FieldAccessMode.FieldReader(f, f.getType())));
                } else {
                    readers.put(entry.getKey(), entry.getValue());
                }
            } else {
                readers.put(entry.getKey(), new CompositeReader(entry.getValue(), existing));
            }
        }

        return readers;
    }

    private Method getMethod(final String methodName, final Class<?> type, final Class<?>... args) {
        try {
            if (alwaysPreferMethodVisibility) {
                return type.getDeclaredMethod(methodName, args);
            }
            return type.getMethod(methodName, args);
        } catch (final NoSuchMethodException e) {
            if (alwaysPreferMethodVisibility) {
                try {
                    return type.getMethod(methodName, args);
                } catch (final NoSuchMethodException e2) {
                    // no-op
                }
            }
            return null;
        }
    }

    private Field getField(final String fieldName, final Class<?> type) {
        Class<?> t = type;
        while (t != Object.class && t != null) {
            try {
                return t.getDeclaredField(fieldName);
            } catch (final NoSuchFieldException e) {
                // no-op
            }
            t = t.getSuperclass();
        }
        return null;
    }

    @Override
    public Map<String, Writer> doFindWriters(final Class<?> clazz) {
        final Map<String, Writer> fieldWriters = this.fields.findWriters(clazz);
        final Map<String, Writer> methodWriters = this.methods.findWriters(clazz);

        final Map<String, Writer> writers = new HashMap<String, Writer>();

        for (final Map.Entry<String, Writer> entry : fieldWriters.entrySet()) {
            final String key = entry.getKey();
            final Method m = getMethod("set" + Character.toUpperCase(key.charAt(0)) + (key.length() > 1 ? key.substring(1) : ""), clazz, toType(entry.getValue().getType()));
            boolean skip = false;
            if (m != null && (ignoreVisibilityFilter || Modifier.isPublic(m.getModifiers()))) {
                for (final Writer w : methodWriters.values()) {
                    if (MethodAccessMode.MethodDecoratedType.class.cast(w).getMethod().equals(m)) {
                        if (w.getAnnotation(JohnzonProperty.class) != null) {
                            skip = true;
                        }
                        break;
                    }
                }
            } else if (!ignoreVisibilityFilter && m != null) {
                continue;
            }
            if (skip) {
                continue;
            }
            writers.put(entry.getKey(), entry.getValue());
        }

        for (final Map.Entry<String, Writer> entry : methodWriters.entrySet()) {
            final Method mr = MethodAccessMode.MethodDecoratedType.class.cast(entry.getValue()).getMethod();
            final String fieldName = BeanUtil.decapitalize(mr.getName().startsWith("is") ? mr.getName().substring(2) : mr.getName().substring(3));
            final Field f = getField(fieldName, clazz);
            boolean skip = false;
            if (f != null) {
                for (final Writer w : fieldWriters.values()) {
                    if (FieldAccessMode.FieldDecoratedType.class.cast(w).getField().equals(f)) {
                        if (w.getAnnotation(JohnzonProperty.class) != null) {
                            skip = true;
                        }
                        break;
                    }
                }
            }
            if (skip) {
                continue;
            }

            final Writer existing = writers.get(entry.getKey());
            if (existing == null) {
                if (f != null) { // useful to hold the Field and transient state for example, just as fallback
                    writers.put(entry.getKey(), new CompositeWriter(
                            entry.getValue(), new FieldAccessMode.FieldWriter(f, f.getType())));
                } else {
                    writers.put(entry.getKey(), entry.getValue());
                }
            } else {
                writers.put(entry.getKey(), new CompositeWriter(entry.getValue(), existing));
            }
        }
        return writers;
    }

    private Class<?> toType(final Type type) {
        return Class.class.isInstance(type) ? Class.class.cast(type) :
                (ParameterizedType.class.isInstance(type) ? toType(ParameterizedType.class.cast(type).getRawType()) :
                        Object.class /*fallback*/);
    }

    public static abstract class CompositeDecoratedType<T extends DecoratedType> implements DecoratedType {
        protected final T type1;
        protected final T type2;

        private CompositeDecoratedType(final T type1, final T type2) {
            this.type1 = type1;
            this.type2 = type2;
        }

        @Override
        public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
            final T found = type1.getClassOrPackageAnnotation(clazz);
            return found == null ? type2.getClassOrPackageAnnotation(clazz) : found;
        }

        @Override
        public Adapter<?, ?> findConverter() {
            final Adapter<?, ?> converter = type1.findConverter();
            return converter != null ? converter : type2.findConverter();
        }

        @Override
        public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
            final T found = type1.getAnnotation(clazz);
            return found == null ? type2.getAnnotation(clazz) : found;
        }

        @Override
        public Type getType() {
            return type1.getType();
        }

        @Override
        public boolean isNillable(final boolean global) {
            return type1.isNillable(global) || type2.isNillable(global);
        }

        public DecoratedType getType1() {
            return type1;
        }

        public DecoratedType getType2() {
            return type2;
        }

        @Override
        public String toString() {
            return "CompositeDecoratedType{" +
                    "type1=" + type1 +
                    ", type2=" + type2 +
                    '}';
        }
    }

    public static final class CompositeReader extends CompositeDecoratedType<Reader> implements Reader {
        private CompositeReader(final Reader type1, final Reader type2) {
            super(type1, type2);
        }

        @Override
        public Object read(final Object instance) {
            return type1.read(instance);
        }

        @Override
        public ObjectConverter.Writer<?> findObjectConverterWriter() {
            final ObjectConverter.Writer<?> objectConverter = type2.findObjectConverterWriter();
            return objectConverter == null ? type1.findObjectConverterWriter() : objectConverter;
        }
    }

    public static final class CompositeWriter extends CompositeDecoratedType<Writer> implements Writer {
        private CompositeWriter(final Writer type1, final Writer type2) {
            super(type1, type2);
        }

        @Override
        public void write(final Object instance, final Object value) {
            type1.write(instance, value);
        }

        @Override
        public ObjectConverter.Reader<?> findObjectConverterReader() {
            final ObjectConverter.Reader<?> objectConverter = type2.findObjectConverterReader();
            return objectConverter == null ? type1.findObjectConverterReader() : objectConverter;
        }
    }
}
