/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.admin.monitor.stats;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import org.glassfish.j2ee.statistics.Stats;
import org.glassfish.j2ee.statistics.Statistic;

/**
 * Provides for generic implementation of any Stats interface. This class facilitates
 * composition over inheritance for all the classes that implement their
 * specific Stats interfaces. None of them has to implement the methods defined
 * by the {@link org.glassfish.j2ee.statistics.Stats} interface. This class
 * implements the same interface and does that job. All that implementing classes
 * have to do is implement the specific accessing methods in their Stats interfaces
 * and delegate the rest to this class. <b> This class invokes all these methods in
 * implementing class through introspection. </b>
 *
 * @author Kedar Mhaswade
 * @since S1AS8.0
 * @version $Version$
 */
public class GenericStatsImpl implements Stats {

    private final Class     statsInterface;
    private final Object    statsProvider;
    /** A map with binding of a String XXX to a method with name <b>get</b>XXX */
    private final Map       getters;

    /**
     */
    public GenericStatsImpl(String statsInterfaceName, Object statsProvider)
    throws ClassNotFoundException {
        this(statsInterfaceName, GenericStatsImpl.class.getClassLoader(), statsProvider);
    }

    /**
     */
    public GenericStatsImpl(String statsInterfaceName, ClassLoader loader,
    Object statsProvider) throws ClassNotFoundException {
        this(Class.forName(statsInterfaceName, true, loader), statsProvider);
    }

    /** Constructs a new instance of this class for a given interface and its implementation.
     * It is mandatory that following contract is satisfied to call this satisfactorily:
     * <ul>
     *  <li> None of the parameters are null. </li>
     *  <li> Given statsProvider implements the given statsInterface. </li>
     *  <li> Given statsInterface has to extend the @{link Stats} interface. </li>
     * </ul>
     * Note that it is expected (though not mandatory) to have a getXXX method that
     * does not return an instance of {@link Statistic} interface.
     * @throws NullPointerException     if any of the given parameters are null
     * @throws IllegalArgumentException if the contract is not satisfied by given parameters
     */
    public GenericStatsImpl(Class statsInterface, Object statsProvider) {
        if (! implementsInterface(statsInterface, statsProvider) ||
            ! extendsStatsInterface(statsInterface)) {
            throw new IllegalArgumentException("Contract violation: invalid interface-implementation pair");
        }
        this.statsProvider  = statsProvider;
        this.statsInterface = statsInterface;
        this.getters        = new HashMap();
        populateGetterMap();
    }

    @Override
    public Statistic getStatistic(String statisticName) {
        final Method getter = (Method) getters.get(statisticName);
        assert (getter != null) : ("Getter not initialized properly: " + statisticName);
        Object result = null;
        try {
            result = getter.invoke(statsProvider);
        }
        catch(Exception e) {
            final RuntimeException oe = new IllegalStateException();
            oe.initCause(e);
            throw oe;
        }
        return ( (Statistic)result );
    }

    @Override
    public String[] getStatisticNames() {
        /* The return array is fixed at the construction time */
        final String[] names = new String[getters.size()];
        return ( (String[])getters.keySet().toArray(names) ); //TODOOOOOOO
    }

    @Override
    public Statistic[] getStatistics() {
        return ( getStatisticsOneByOne() );         //invokes sequentially
    }

    private Statistic[] getStatisticsOneByOne() {
        final Iterator iter     = getters.keySet().iterator();
        final Statistic[] stats = new Statistic[getters.keySet().size()];
        int i = 0;
        while (iter.hasNext()) {
            final String sn = (String) iter.next();
            stats[i++] = this.getStatistic(sn);
        }
        assert (stats.length == i);
        return ( stats );
    }

    private boolean implementsInterface(Class c, Object o) {
        boolean impls = false;
        final Class[] interfaces = o.getClass().getInterfaces();
        for (Class element : interfaces) {
            if (element.equals(c)){
                impls = true;
                break;
            }
        }
        return ( impls );
    }

    private boolean extendsStatsInterface(Class i) {
        final Class statsInterface = org.glassfish.j2ee.statistics.Stats.class;
        return ( statsInterface.isAssignableFrom(i) );
    }

    private void populateGetterMap() {
        // Fix for Bugs 5045435, 6172088
        //final Method[] apis     = statsInterface.getDeclaredMethods(); //all of these should be PUBLIC.
        final Method[] m = statsInterface.getMethods();
        // exclude methods that belong to the javax.management.j2ee.Stats
        final Method[] apis     = filterStatsMethods(m);
        final Method[] methods  = getGetters(apis);
        final String[] names    = methods2Statistics(methods);
        assert (names.length == methods.length) : ("Statistic names array is not having same length as that of array of getters");
        int i;
        for (i = 0 ; i < names.length ; i++) {
            getters.put(names[i], methods[i]);
        }
        assert (getters.size() == i) : ("Getters map is incorrect, names.length = " + names.length + " methods.length = " + methods.length);
    }

    private Method[] getGetters(Method[] all) {
        final ArrayList l = new ArrayList();
        for (final Method am : all) {
            if (isValidGetter(am)) {
                l.add(am);
            }
        }
        final Method[] m = new Method[l.size()];
        return ( (Method[])l.toArray(m) );
    }

    private boolean isValidGetter(Method m) {
        final boolean startsWithGet     = m.getName().startsWith("get");
        final boolean hasNoParams       = m.getParameterTypes().length == 0;
        final boolean returnsStatistic  = Statistic.class.isAssignableFrom(m.getReturnType());

        return ( startsWithGet && hasNoParams && returnsStatistic );
    }

    private String[] methods2Statistics(Method[] methods) {
        final String[] names = new String[methods.length];
        for (int i = 0 ; i < methods.length ; i++) {
            final String    m = methods[i].getName();
            final int       s = "get".length();
            names[i] = m.substring(s);
        }
        return ( names );
    }

    private boolean isStatsInterfaceMethod(String name) {
        final Method[] methods = org.glassfish.j2ee.statistics.Stats.class.getMethods();
        boolean isInterfaceMethod = false;
        for (Method method : methods) {
            if (method.getName().equals(name)) {
                isInterfaceMethod = true;
                break;
            }
        }
        return ( isInterfaceMethod );
    }

    private Method[] filterStatsMethods(Method[] m) {
        ArrayList methodList = new ArrayList();
        for (Method element : m) {
            if(! isStatsInterfaceMethod(element.getName())) {
                methodList.add(element);
            }
        }
        final Method[] methods = new Method[methodList.size()];
        return (Method[])methodList.toArray(methods);
    }
}
