/*
 * Copyright (c) 2017, 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.s1asdev.jdbc.statementwrapper.client;

import javax.naming.*;

import com.sun.s1asdev.jdbc.statementwrapper.ejb.SimpleBMPHome;
import com.sun.s1asdev.jdbc.statementwrapper.ejb.SimpleBMP;
import com.sun.ejte.ccl.reporter.SimpleReporterAdapter;

import java.util.TimerTask;
import java.util.Timer;

import javax.naming.*;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;


public class SimpleBMPClient {
 
    private static long count = 0;
    private static final Object lock = new Integer(10);
    private long totalIterations = 0;
    private static int no_of_get_connections = 5;

    public static final String NUM_CON_ACQUIRED_COUNT = "numconnacquired";
    public static final int JMX_PORT = 8686;
    public static final String HOST_NAME = "localhost";

    private static        SimpleReporterAdapter stat = new SimpleReporterAdapter();
    private static            String testSuite = "";


    public static void main(String[] args)
            throws Exception {
        int no_of_threads = 20;
        long duration = 5 * 60 * 1000;
        if (args != null && args.length > 0) {
            try {
                no_of_threads = Integer.parseInt(args[0]);
                System.out.println("Setting no of threads to : " + args[0]);
            } catch (Exception e) {
            }
        }

        if (args != null && args.length > 1) {
            try {
                duration = Integer.parseInt(args[1]) * 60 * 1000;
                System.out.println("Setting duration to  " + args[1] + " minutes");
            } catch (Exception e) {
            }
        }

        if (args != null && args.length > 2) {
            try {
                no_of_get_connections = Integer.parseInt(args[2]);
                System.out.println("Setting no-of-get-connections to  " + args[2]);
            } catch (Exception e) {
            }
        }
        final MyThread threads[] = new MyThread[no_of_threads];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new MyThread();
            threads[i].setNoOfGetConnections(no_of_get_connections);
        }

        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
//        System.out.println("Started at : " + 

        TimerTask task = new TimerTask() {
            public void run() {
                for (int i = 0; i < threads.length; i++) {
                    threads[i].setExit(true);
                }
              try{
                  Thread.currentThread().sleep(5000);
              }catch(Exception e){
              }
            try{
            long totalCount = count*no_of_get_connections;
//            System.out.println("TOTAL COUNT : " + count*no_of_get_connections);
            long monitoringCount = getMonitorablePropertyOfConnectionPool("ql-jdbc-pool") ;
            System.out.println("-----------------------------------------------------------------------------------");
            System.out.println("Total getConnection() : " + totalCount + ", monitoring-count : " + monitoringCount);
            System.out.println("-----------------------------------------------------------------------------------");
      
            if(totalCount == monitoringCount){
                stat.addStatus(testSuite + " Perf-test : ", stat.PASS);
            }else{
                stat.addStatus(testSuite + " Perf-test : ", stat.FAIL);
            }
            }catch(Exception e){
                e.printStackTrace();
            }
            stat.printSummary();
           
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, duration);
//        System.out.println("Total Count : " + count);
    }
 public static int getMonitorablePropertyOfConnectionPool(String poolName) throws Exception {

        final String urlStr = "service:jmx:rmi:///jndi/rmi://" + HOST_NAME + ":" + JMX_PORT + "/jmxrmi";
        final JMXServiceURL url = new JMXServiceURL(urlStr);

        final JMXConnector jmxConn = JMXConnectorFactory.connect(url);
        final MBeanServerConnection connection = jmxConn.getMBeanServerConnection();

        ObjectName objectName =
                new ObjectName("amx:pp=/mon/server-mon[server],type=jdbc-connection-pool-mon,name=resources/" + poolName);

        javax.management.openmbean.CompositeDataSupport returnValue =
                (javax.management.openmbean.CompositeDataSupport)
                connection.getAttribute(objectName, NUM_CON_ACQUIRED_COUNT);

        return new Integer(returnValue.get("count").toString());
    }


    static class MyThread extends Thread {
        SimpleBMP simpleBMP = null;
        boolean exit = false;
        int no_of_get_connections = 5;

        public void setNoOfGetConnections(int no_of_get_connections) {
            this.no_of_get_connections = no_of_get_connections;
        }

        public void setExit(boolean exit) {
            this.exit = exit;
        }

        public MyThread() throws Exception {
            InitialContext ic = new InitialContext();
            Object objRef = ic.lookup("java:comp/env/ejb/SimpleBMPHome");
            SimpleBMPHome simpleBMPHome = (SimpleBMPHome)
                    javax.rmi.PortableRemoteObject.narrow(objRef, SimpleBMPHome.class);
            simpleBMP = simpleBMPHome.create();
        }

        public void runTest() throws Exception {

            long iterations = 0;
            long passed = 0;
            long failed = 0;
            while (!exit) {
                if (simpleBMP.test1(no_of_get_connections)) {
                //if (simpleBMP.test2()) {
                    passed++;
                } else {
                    failed++;
                }
                    synchronized(lock){
                        count++;
                    }
                iterations++;
            }

            //stat.addStatus(testSuite + " statementTest : THREAD :  " + Thread.currentThread().getName(), stat.PASS);
            //stat.addStatus(testSuite + " statementTest : PASS COUNT :  " + passed, stat.PASS);
            //stat.addStatus(testSuite + " statementTest : FAIL COUNT : " + failed, stat.PASS);
            //stat.addStatus(testSuite + " statementTest : TOTAL ITERATIONS : " + iterations, stat.PASS);
            //stat.printSummary();
        }

        public void run() {
            while (!exit) {
                try {
                    runTest();
                } catch (Exception e) {
                }
            }
        }
    }
}
