/*
 * Copyright (c) 2014, 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;
        }
        initialize(this.write);
        initialize(this.read);
        return true;
    }

    private void 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();
                }
            }
        }
    }

    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();
    }
}
