/*
 * 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.
 */

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.util.FastMath;

/*
 * plot 'logGamma.dat' binary format="%double%double" endian=big u 1:2 w l
 */
public class RealFunctionValidation {

    public static class MissingRequiredPropertyException
        extends IllegalArgumentException {

        private static final long serialVersionUID = 20121017L;

        public MissingRequiredPropertyException(final String key) {

            super("missing required property " + key);
        }
    }

    public static class ApplicationProperties {

        private static final int DOT = '.';

        private static final String METHOD_KEY = "method";

        private static final String SIGNATURE_KEY = "signature";

        private static final String INPUT_FILE_MASK = "inputFileMask";

        private static final String OUTPUT_FILE_MASK = "outputFileMask";

        private static final String FROM_KEY = "from";

        private static final String TO_KEY = "to";

        private static final String BY_KEY = "by";

        final Method method;

        final String inputFileMask;

        final String outputFileMask;

        final int from;

        final int to;

        final int by;

        /**
         * Returns a {@link Method} with specified signature.
         *
         * @param className The fully qualified name of the class to which the
         * method belongs.
         * @param methodName The name of the method.
         * @param signature The signature of the method, as a list of parameter
         * types.
         * @return the method
         * @throws SecurityException
         * @throws ClassNotFoundException
         */
        public static Method findStaticMethod(final String className,
                                              final String methodName,
                                              final List<Class<?>> signature)
            throws SecurityException, ClassNotFoundException {

            final int n = signature.size();
            final Method[] methods = Class.forName(className).getMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    final Class<?>[] parameters = method.getParameterTypes();
                    boolean sameSignature = true;
                    if (parameters.length == n) {
                        for (int i = 0; i < n; i++) {
                            sameSignature &= signature.get(i)
                                .equals(parameters[i]);
                        }
                        if (sameSignature) {
                            final int modifiers = method.getModifiers();
                            if ((modifiers & Modifier.STATIC) != 0) {
                                return method;
                            } else {
                                final String msg = "method must be static";
                                throw new IllegalArgumentException(msg);
                            }
                        }
                    }
                }
            }
            throw new IllegalArgumentException("method not found");
        }

        public static Class<?> parsePrimitiveType(final String type) {

            if (type.equals("boolean")) {
                return Boolean.TYPE;
            } else if (type.equals("byte")) {
                return Byte.TYPE;
            } else if (type.equals("char")) {
                return Character.TYPE;
            } else if (type.equals("double")) {
                return Double.TYPE;
            } else if (type.equals("float")) {
                return Float.TYPE;
            } else if (type.equals("int")) {
                return Integer.TYPE;
            } else if (type.equals("long")) {
                return Long.TYPE;
            } else if (type.equals("short")) {
                return Short.TYPE;
            } else {
                final StringBuilder builder = new StringBuilder();
                builder.append(type).append(" is not a primitive type");
                throw new IllegalArgumentException(builder.toString());
            }
        }

        private static String getPropertyAsString(final Properties properties,
                                                  final String key) {

            final String value = properties.getProperty(key);
            if (value == null) {
                throw new MissingRequiredPropertyException(key);
            } else {
                return value;
            }
        }

        private static int getPropertyAsInteger(final Properties properties,
                                                final String key) {

            final String value = properties.getProperty(key);
            if (value == null) {
                throw new MissingRequiredPropertyException(key);
            } else {
                return Integer.parseInt(value);
            }
        }

        private ApplicationProperties(final String fullyQualifiedName,
                                      final String signature,
                                      final String inputFileMask,
                                      final String outputFileMask,
                                      final int from, final int to, final int by) {

            this.inputFileMask = inputFileMask;
            this.outputFileMask = outputFileMask;
            this.from = from;
            this.to = to;
            this.by = by;

            final String[] types = signature.split(",");
            final List<Class<?>> parameterTypes = new ArrayList<Class<?>>();
            for (String type : types) {
                parameterTypes.add(parsePrimitiveType(type.trim()));
            }
            final int index = fullyQualifiedName.lastIndexOf(DOT);
            try {
                final String className, methodName;
                className = fullyQualifiedName.substring(0, index);
                methodName = fullyQualifiedName.substring(index + 1);
                this.method = findStaticMethod(className, methodName,
                                               parameterTypes);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException(e);
            }

        }

        public static final ApplicationProperties create(final Properties properties) {

            final String methodFullyQualifiedName;
            methodFullyQualifiedName = getPropertyAsString(properties,
                                                           METHOD_KEY);

            final String signature;
            signature = getPropertyAsString(properties, SIGNATURE_KEY);

            final String inputFileMask;
            inputFileMask = getPropertyAsString(properties, INPUT_FILE_MASK);

            final String outputFileMask;
            outputFileMask = getPropertyAsString(properties, OUTPUT_FILE_MASK);

            final int from = getPropertyAsInteger(properties, FROM_KEY);
            final int to = getPropertyAsInteger(properties, TO_KEY);
            final int by = getPropertyAsInteger(properties, BY_KEY);

            return new ApplicationProperties(methodFullyQualifiedName,
                                             signature, inputFileMask,
                                             outputFileMask, from, to, by);
        }
    };

    public static Object readAndWritePrimitiveValue(final DataInputStream in,
                                                    final DataOutputStream out,
                                                    final Class<?> type)
        throws IOException {

        if (!type.isPrimitive()) {
            throw new IllegalArgumentException("type must be primitive");
        }
        if (type.equals(Boolean.TYPE)) {
            final boolean x = in.readBoolean();
            out.writeBoolean(x);
            return Boolean.valueOf(x);
        } else if (type.equals(Byte.TYPE)) {
            final byte x = in.readByte();
            out.writeByte(x);
            return Byte.valueOf(x);
        } else if (type.equals(Character.TYPE)) {
            final char x = in.readChar();
            out.writeChar(x);
            return Character.valueOf(x);
        } else if (type.equals(Double.TYPE)) {
            final double x = in.readDouble();
            out.writeDouble(x);
            return Double.valueOf(x);
        } else if (type.equals(Float.TYPE)) {
            final float x = in.readFloat();
            out.writeFloat(x);
            return Float.valueOf(x);
        } else if (type.equals(Integer.TYPE)) {
            final int x = in.readInt();
            out.writeInt(x);
            return Integer.valueOf(x);
        } else if (type.equals(Long.TYPE)) {
            final long x = in.readLong();
            out.writeLong(x);
            return Long.valueOf(x);
        } else if (type.equals(Short.TYPE)) {
            final short x = in.readShort();
            out.writeShort(x);
            return Short.valueOf(x);
        } else {
            // This should never occur.
            throw new IllegalStateException();
        }
    }

    public static SummaryStatistics assessAccuracy(final Method method,
                                                   final DataInputStream in,
                                                   final DataOutputStream out)
        throws IOException, IllegalAccessException, IllegalArgumentException,
        InvocationTargetException {

        if (method.getReturnType() != Double.TYPE) {
            throw new IllegalArgumentException("method must return a double");
        }

        final Class<?>[] types = method.getParameterTypes();
        for (int i = 0; i < types.length; i++) {
            if (!types[i].isPrimitive()) {
                final StringBuilder builder = new StringBuilder();
                builder.append("argument #").append(i + 1)
                    .append(" of method ").append(method.getName())
                    .append("must be of primitive of type");
                throw new IllegalArgumentException(builder.toString());
            }
        }

        final SummaryStatistics stat = new SummaryStatistics();
        final Object[] parameters = new Object[types.length];
        while (true) {
            try {
                for (int i = 0; i < parameters.length; i++) {
                    parameters[i] = readAndWritePrimitiveValue(in, out,
                                                               types[i]);
                }
                final double expected = in.readDouble();
                if (FastMath.abs(expected) > 1E-16) {
                    final Object value = method.invoke(null, parameters);
                    final double actual = ((Double) value).doubleValue();
                    final double err = FastMath.abs(actual - expected);
                    final double ulps = err / FastMath.ulp(expected);
                    out.writeDouble(expected);
                    out.writeDouble(actual);
                    out.writeDouble(ulps);
                    stat.addValue(ulps);
                }
            } catch (EOFException e) {
                break;
            }
        }
        return stat;
    }

    public static void run(final ApplicationProperties properties)
        throws IllegalAccessException, IllegalArgumentException,
        InvocationTargetException, IOException {

        for (int i = properties.from; i < properties.to; i += properties.by) {
            final String inputFileName;
            inputFileName = String.format(properties.inputFileMask, i);
            final String outputFileName;
            outputFileName = String.format(properties.outputFileMask, i);

            final DataInputStream in;
            in = new DataInputStream(new FileInputStream(inputFileName));
            final DataOutputStream out;
            out = new DataOutputStream(new FileOutputStream(outputFileName));

            final SummaryStatistics stats;
            stats = assessAccuracy(properties.method, in, out);

            System.out.println("input file name = " + inputFileName);
            System.out.println("output file name = " + outputFileName);
            System.out.println(stats);
        }
    }

    public static void main(final String[] args)
        throws IOException, IllegalAccessException, IllegalArgumentException,
        InvocationTargetException {

        if (args.length == 0) {
            final String msg = "missing required properties file";
            throw new IllegalArgumentException(msg);
        }

        final FileInputStream in = new FileInputStream(args[0]);
        final Properties properties = new Properties();
        properties.load(in);
        in.close();

        final ApplicationProperties p;
        p = ApplicationProperties.create(properties);

        run(p);
    }
}
