/*
 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.beans.introspect;

import java.beans.BeanProperty;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static com.sun.beans.finder.ClassFinder.findClass;

public final class PropertyInfo {

    public enum Name {
        bound, expert, hidden, preferred, required, visualUpdate, description,
        enumerationValues
    }

    private static final String VETO_EXCEPTION_NAME = "java.beans.PropertyVetoException";
    private static final Class<?> VETO_EXCEPTION;

    static {
        Class<?> type;
        try {
            type = Class.forName(VETO_EXCEPTION_NAME);
        } catch (Exception exception) {
            type = null;
        }
        VETO_EXCEPTION = type;
    }

    private Class<?> type;
    private MethodInfo read;
    private MethodInfo write;
    private PropertyInfo indexed;
    private List<MethodInfo> readList;
    private List<MethodInfo> writeList;
    private Map<Name,Object> map;

    private PropertyInfo() {
    }

    private boolean initialize() {
        if (this.read != null) {
            this.type = this.read.type;
        }
        if (this.readList != null) {
            for (MethodInfo info : this.readList) {
                if ((this.read == null) || this.read.type.isAssignableFrom(info.type)) {
                    this.read = info;
                    this.type = info.type;
                }
            }
            this.readList = null;
        }
        if (this.writeList != null) {
            for (MethodInfo info : this.writeList) {
                if (this.type == null) {
                    this.write = info;
                    this.type = info.type;
                } else if (this.type.isAssignableFrom(info.type)) {
                    if ((this.write == null) || this.write.type.isAssignableFrom(info.type)) {
                        this.write = info;
                    }
                }
            }
            this.writeList = null;
        }
        if (this.indexed != null) {
            if ((this.type != null) && !this.type.isArray()) {
                this.indexed = null; // property type is not an array
            } else if (!this.indexed.initialize()) {
                this.indexed = null; // cannot initialize indexed methods
            } else if ((this.type != null) && (this.indexed.type != this.type.getComponentType())) {
                this.indexed = null; // different property types
            } else {
                this.map = this.indexed.map;
                this.indexed.map = null;
            }
        }
        if ((this.type == null) && (this.indexed == null)) {
            return false;
        }
        boolean done = initialize(this.read);
        if (!done) {
            initialize(this.write);
        }
        return true;
    }

    private boolean initialize(MethodInfo info) {
        if (info != null) {
            BeanProperty annotation = info.method.getAnnotation(BeanProperty.class);
            if (annotation != null) {
                if (!annotation.bound()) {
                    put(Name.bound, Boolean.FALSE);
                }
                put(Name.expert, annotation.expert());
                put(Name.required, annotation.required());
                put(Name.hidden, annotation.hidden());
                put(Name.preferred, annotation.preferred());
                put(Name.visualUpdate, annotation.visualUpdate());
                put(Name.description, annotation.description());
                String[] values = annotation.enumerationValues();
                try {
                    Object[] array = new Object[3 * values.length];
                    int index = 0;
                    for (String value : values) {
                        Class<?> type = info.method.getDeclaringClass();
                        String name = value;
                        int pos = value.lastIndexOf('.');
                        if (pos > 0) {
                            name = value.substring(0, pos);
                            if (name.indexOf('.') < 0) {
                                String pkg = type.getName();
                                name = pkg.substring(0, 1 + Math.max(
                                        pkg.lastIndexOf('.'),
                                        pkg.lastIndexOf('$'))) + name;
                            }
                            type = findClass(name);
                            name = value.substring(pos + 1);
                        }
                        Field field = type.getField(name);
                        if (Modifier.isStatic(field.getModifiers()) && info.type.isAssignableFrom(field.getType())) {
                            array[index++] = name;
                            array[index++] = field.get(null);
                            array[index++] = value;
                        }
                    }
                    if (index == array.length) {
                        put(Name.enumerationValues, array);
                    }
                } catch (Exception ignored) {
                    ignored.printStackTrace();
                }
                return true;
            }
        }
        return false;
    }

    public Class<?> getPropertyType() {
        return this.type;
    }

    public Method getReadMethod() {
        return (this.read == null) ? null : this.read.method;
    }

    public Method getWriteMethod() {
        return (this.write == null) ? null : this.write.method;
    }

    public PropertyInfo getIndexed() {
        return this.indexed;
    }

    public boolean isConstrained() {
        if (this.write != null) {
            if (VETO_EXCEPTION == null) {
                for (Class<?> type : this.write.method.getExceptionTypes()) {
                    if (type.getName().equals(VETO_EXCEPTION_NAME)) {
                        return true;
                    }
                }
            } else if (this.write.isThrow(VETO_EXCEPTION)) {
                return true;
            }
        }
        return (this.indexed != null) && this.indexed.isConstrained();
    }

    public boolean is(Name name) {
        Object value = get(name);
        return (value instanceof Boolean)
                ? (Boolean) value
                : Name.bound.equals(name);
    }

    public Object get(Name name) {
        return this.map == null ? null : this.map.get(name);
    }

    private void put(Name name, boolean value) {
        if (value) {
            put(name, Boolean.TRUE);
        }
    }

    private void put(Name name, String value) {
        if (0 < value.length()) {
            put(name, (Object) value);
        }
    }

    private void put(Name name, Object value) {
        if (this.map == null) {
            this.map = new EnumMap<>(Name.class);
        }
        this.map.put(name, value);
    }

    private static List<MethodInfo> add(List<MethodInfo> list, Method method, Type type) {
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(new MethodInfo(method, type));
        return list;
    }

    private static boolean isPrefix(String name, String prefix) {
        return name.length() > prefix.length() && name.startsWith(prefix);
    }

    private static PropertyInfo getInfo(Map<String,PropertyInfo> map, String key, boolean indexed) {
        PropertyInfo info = map.get(key);
        if (info == null) {
            info = new PropertyInfo();
            map.put(key, info);
        }
        if (!indexed) {
            return info;
        }
        if (info.indexed == null) {
            info.indexed = new PropertyInfo();
        }
        return info.indexed;
    }

    public static Map<String,PropertyInfo> get(Class<?> type) {
        List<Method> methods = ClassInfo.get(type).getMethods();
        if (methods.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String,PropertyInfo> map = new TreeMap<>();
        for (Method method : methods) {
            if (!Modifier.isStatic(method.getModifiers())) {
                Class<?> returnType = method.getReturnType();
                String name = method.getName();
                switch (method.getParameterCount()) {
                    case 0:
                        if (returnType.equals(boolean.class) && isPrefix(name, "is")) {
                            PropertyInfo info = getInfo(map, name.substring(2), false);
                            info.read = new MethodInfo(method, boolean.class);
                        } else if (!returnType.equals(void.class) && isPrefix(name, "get")) {
                            PropertyInfo info = getInfo(map, name.substring(3), false);
                            info.readList = add(info.readList, method, method.getGenericReturnType());
                        }
                        break;
                    case 1:
                        if (returnType.equals(void.class) && isPrefix(name, "set")) {
                            PropertyInfo info = getInfo(map, name.substring(3), false);
                            info.writeList = add(info.writeList, method, method.getGenericParameterTypes()[0]);
                        } else if (!returnType.equals(void.class) && method.getParameterTypes()[0].equals(int.class) && isPrefix(name, "get")) {
                            PropertyInfo info = getInfo(map, name.substring(3), true);
                            info.readList = add(info.readList, method, method.getGenericReturnType());
                        }
                        break;
                    case 2:
                        if (returnType.equals(void.class) && method.getParameterTypes()[0].equals(int.class) && isPrefix(name, "set")) {
                            PropertyInfo info = getInfo(map, name.substring(3), true);
                            info.writeList = add(info.writeList, method, method.getGenericParameterTypes()[1]);
                        }
                        break;
                }
            }
        }
        Iterator<PropertyInfo> iterator = map.values().iterator();
        while (iterator.hasNext()) {
            if (!iterator.next().initialize()) {
                iterator.remove();
            }
        }
        return !map.isEmpty()
                ? Collections.unmodifiableMap(map)
                : Collections.emptyMap();
    }
}
