/*
 * 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.pooling.ejb;

import jakarta.ejb.*;
import javax.naming.*;
import javax.sql.*;
import java.rmi.*;
import java.util.*;
import java.sql.*;
import jakarta.transaction.SystemException;
import jakarta.transaction.UserTransaction;

public class SimpleSessionBean implements SessionBean
{

    private SessionContext context;
    private static int count = 10;
    private static boolean rollback;
    private static String tableName = "COFFEE";
    private InitialContext ic;
    private DataSource ds;
    private DataSource xads;
    private DataSource contds;
    private static boolean isXA=false;
    public void setSessionContext(SessionContext ctxt) {
        this.context = ctxt;
    try {
        ic = new InitialContext();
        ds = (DataSource)ic.lookup("java:comp/env/DataSource");
        xads = (DataSource)ic.lookup("java:comp/env/XADataSource");
        contds = (DataSource) ic.lookup("java:comp/env/ContainerDataSource");
    } catch( Exception ne ) {
        ne.printStackTrace();
    }
    }

    public void ejbCreate() throws CreateException {
    }

    public boolean test1(boolean isXa, boolean rollback) {
    boolean passed = false;
    this.isXA = isXa;
    this.rollback = rollback;
    DataSource ds = null;
    if(isXA) {
        ds = this.xads;
    } else {
        ds = this.ds;
    }
        UserTransaction ut = null;
        try {

            createTable(ds);

            int count1 = getCount(ds);
            System.out.println("count1 : " + count1);

            ut = (UserTransaction) context.getUserTransaction();
            ut.begin();

            for(int i=0; i< count; i++)
                insertRow(ds);
            if(rollback)
                ut.rollback();
            else
                ut.commit();

            int count2=getCount(ds);

            System.out.println("count2 : " + count2);

            int diff = count2 - count1;
            if(( diff == count && !rollback) || (diff == 0 && rollback))
                passed = true;
            else
                passed = false;

        } catch(Exception e){
            passed = false;
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        };
    return passed;

    }

    public boolean test2(boolean isXa, boolean rollback) {
    boolean passed = false;
    this.isXA = isXa;
    this.rollback = rollback;
    DataSource ds = null;
    if(isXA) {
        ds = this.xads;
    } else {
        ds = this.ds;
    }
        UserTransaction ut = null;
        try {
            Connection[] con;

            createTable(ds);

            int count1 = getCount(ds);
            System.out.println("count1 : " + count1);

            ut = (UserTransaction) context.getUserTransaction();
            ut.begin();

            con = openConnections(ds, count);
            insertRow(con);
            closeConnections(con);

            if(rollback)
                ut.rollback();
            else
                ut.commit();

            int count2=getCount(ds);

            System.out.println("count2 : " + count2);

            int diff = count2 - count1;
            if(( diff == count && !rollback) || (diff == 0 && rollback))
                passed = true;
            else
                passed = false;

        } catch(Exception e){
            passed = false;
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        }
    return passed;
    }

    public boolean test3(boolean rollback) {
    boolean passed = false;
    this.rollback = rollback;
        UserTransaction ut = null;
    DataSource ds1 = this.ds;
    DataSource ds2 = this.xads;
        try {

            isXA = false;
            createTable(ds1);
            isXA = true;
            createTable(ds2);

            isXA = false;
            int count1 = getCount(ds1);
            isXA = true;
            int count3 = getCount(ds2);
            System.out.println("count1 : " + count1);
            System.out.println("count3 : " + count3);

            ut = (UserTransaction) context.getUserTransaction();
            ut.begin();

            isXA = false;
            for(int i=0; i< count; i++)
                insertRow(ds1);
            isXA = true;
            for(int i=0; i< count; i++)
                insertRow(ds2);

            if(rollback)
                ut.rollback();
            else
                ut.commit();

            isXA = false;
            int count2=getCount(ds1);
            isXA = true;
            int count4=getCount(ds2);

            System.out.println("count2 : " + count2);
            System.out.println("count4 : " + count4);

            int diff1 = count2 - count1;
            int diff2 = count4 - count3;
            if((( diff1 == count && !rollback) || (diff1 == 0 && rollback))
            && (( diff2 == count && !rollback) || (diff2 == 0 && rollback)))
                passed=true;
            else
                passed=false;

        } catch(Exception e){
            passed=false;
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        };
       return passed;
    }

    private void createTable(final DataSource ds) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";

        Connection con;
        Statement stmt;
        con = ds.getConnection("scott", "tiger");
        stmt = con.createStatement();

        try{
            stmt.executeUpdate("drop table " + tableName);
        }catch(Exception ex){
            ex.printStackTrace();
        }
        stmt.executeUpdate("create table " + tableName + " (name varchar(32), qty integer)");
        stmt.close();
        con.close();
    }

    private int getCount(final DataSource ds) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        Statement stmt;
        Connection con;
        ResultSet rs;
        con = ds.getConnection("scott", "tiger");
        stmt = con.createStatement();
        rs = stmt.executeQuery( "SELECT count(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        stmt.close();
        con.close();
        return count;
    }

    private void insertRow(final DataSource ds) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        Statement stmt;
        Connection con;
        con = ds.getConnection("scott", "tiger");
        stmt = con.createStatement();
        stmt.executeUpdate("INSERT INTO " + tableName + " values ('COFFEE', 100)");
        stmt.close();
        con.close();
    }

    private void insertRow(final Connection[] con) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        Statement stmt;
        for(int i=0; i < con.length; i++){
            stmt = con[i].createStatement();
            stmt.executeUpdate("INSERT INTO " + tableName + " values ('COFFEE', 100)");
        stmt.close();
        }
    }


    private void printConnection(final DataSource ds) throws SQLException{
        com.sun.appserv.jdbc.DataSource dsTyped = (com.sun.appserv.jdbc.DataSource) ds;
        Connection wrapper = dsTyped.getConnection("scott", "tiger");
        System.out.println("Connection type : " + dsTyped.getConnection(wrapper));
        wrapper.close();
    }

    public boolean openAndCloseConnection(int count) {
    boolean status = true;
    DataSource ds = contds;

        try {
            com.sun.appserv.jdbc.DataSource dsTyped = (com.sun.appserv.jdbc.DataSource) ds;
        HashSet<String> connections = new HashSet<String>();
            Connection con;
        String conType;
        int i = 0;
            for(; i < count; i++){
                con = ds.getConnection();
        conType = dsTyped.getConnection(con).toString();
            System.out.println("Connection type : " + conType);
                con.close();
        if(!connections.add(conType)){
            status = false;
            break;
        }
            }
               System.out.println("Total connection requested :  " + count);
               System.out.println("Total connection created :  " + i);
               System.out.println("Total number of unique connection :  " + connections.size());
        }catch(Exception ex){
            ex.printStackTrace();
        }
    return status;
    }

    public boolean openMaxConnections(int count) {
    boolean status = false;
    DataSource ds = contds;
        Connection[] con = new Connection[count];
    int i = 0;
        for(; i < count; i++){
       try{
               con[i] = ds.getConnection();
       }catch(SQLException ex){
        System.out.println("Unable to create max connections");
        status = false;
       }
    }

    if(i ==  count){
        System.out.println("Able to create max connections");
        status=true;
        try{
            ds.getConnection();
                    System.out.println("Able to create beyond max connections");
                    status=false;
        }catch(SQLException ex){
                    System.out.println("Unable to create beyond max connections");
                status=true;
               }
    }

        for(; i > 0; i--){
       try{
                con[i - 1].close();
       }catch(SQLException ex){
        System.out.println("Unable to close connection");
       }
    }
    return status;
    }

    private Connection[] openConnections(DataSource ds, int count) throws NamingException, SQLException {

        Connection[] con = new Connection[count];
        for(int i=0; i < count; i++)
            con[i] = ds.getConnection("scott", "tiger");

        return con;
    }

    private void closeConnections(Connection[] con) throws SQLException {
        for(int i=0; i < count; i++)
            con[i].close();
    }

    public void ejbLoad() {}
    public void ejbStore() {}
    public void ejbRemove() {}
    public void ejbActivate() {}
    public void ejbPassivate() {}
    public void unsetEntityContext() {}
    public void ejbPostCreate() {}
}
