/*
 * Copyright (c) 2001, 2020 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 mdb;

import connector.MyMessageListener;
import jakarta.ejb.*;
import javax.naming.*;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.sql.*;
import javax.sql.*;
import jakarta.jms.*;
import jakarta.transaction.*;


/**
 */
public class MyMessageBean implements MessageDrivenBean,
        MyMessageListener {

    private transient MessageDrivenContext mdc = null;
    private Context context;

    /**
     * Constructor, which is public and takes no arguments.
     */
    public MyMessageBean() {}

    /**
     * setMessageDrivenContext method, declared as public (but
     * not final or static), with a return type of void, and
     * with one argument of type jakarta.ejb.MessageDrivenContext.
     *
     * @param mdc    the context to set
     */
    public void setMessageDrivenContext(MessageDrivenContext mdc) {
        this.mdc = mdc;
    }

    /**
     * ejbCreate method, declared as public (but not final or
     * static), with a return type of void, and with no
     * arguments.
     */
    public void ejbCreate() { }

    /**
     * onMessage method, declared as public (but not final or
     * static), with a return type of void, and with one argument
     * of type jakarta.jms.Message.
     *
     * Casts the incoming Message to a TextMessage and displays
     * the text.
     *
     * @param inMessage    the incoming message
     */
    public void onMessage(String inMessage) {

        debug("onMessage:: RECEIVED [" + inMessage + "]");

        try {
            if (inMessage.endsWith("WRITE")) {
                doDbStuff("WRITE",
                        inMessage.substring(0, inMessage.lastIndexOf(":")));
            } else if (inMessage.endsWith("DELETE")) {
                doDbStuff("DELETE",
                        inMessage.substring(0, inMessage.lastIndexOf(":")));
            } else if (inMessage.endsWith("DELETE_ALL")) {
                doDbStuff("DELETE_ALL", "::");
            } else {
                //unsupported op.
            }
        } catch (Exception ex) {
            debug("UH OH...");
            ex.printStackTrace();
        }

    }

    /**
     * ejbRemove method, declared as public (but not final or
     * static), with a return type of void, and with no
     * arguments.
     */
    public void ejbRemove() {}


    private void doDbStuff(String op, String message) throws Exception {

        java.sql.Connection dbConnection = null;
        String id    = message.substring(0, message.indexOf(":"));
        String body  = message.substring(message.indexOf(":")+1);
        try {
            Context ic = new InitialContext();

            if ("READ".equals(op)) {

                debug("Reading row from database...");

                // Creating a database connection

                  DataSource ds = (DataSource) ic.lookup("java:comp/env/MyDB");
                  debug("Looked up Datasource\n");
                  debug("Get JDBC connection, auto sign on");
                  dbConnection = ds.getConnection();

                  Statement stmt = dbConnection.createStatement();
                  String query =
                  "SELECT id from messages where id = 'QQ'";
                  ResultSet results = stmt.executeQuery(query);
                  results.next();
                  System.out.println("QQ has balance " +
                  results.getInt("balance") + " dollars");
                  results.close();
                  stmt.close();

                  System.out.println("Read one account\n");

            } else if ("WRITE".equals(op)) {

                debug("Inserting one message in the database\n");

                // Creating a database connection
                DataSource ds = (DataSource) ic.lookup("java:comp/env/MyDB");
                //debug("Looked up Datasource\n");
                //debug("Get JDBC connection, auto sign on");
                dbConnection = ds.getConnection();

                createRow(id, body, dbConnection);
                System.out.println("Created one message\n");

            } else if ("DELETE".equals(op)) {

                debug("Deleting one message from the database\n");

                // Creating a database connection
                DataSource ds = (DataSource) ic.lookup("java:comp/env/MyDB");
                //debug("Looked up Datasource\n");
                //debug("Get JDBC connection, auto sign on");
                dbConnection = ds.getConnection();

                deleteRow(id, dbConnection);
                System.out.println("Deleted one message\n");
            } else if ("DELETE_ALL".equals(op)) {

                debug("Deleting all messages from the database\n");

                // Creating a database connection
                DataSource ds = (DataSource) ic.lookup("java:comp/env/MyDB");
                //debug("Looked up Datasource\n");
                //debug("Get JDBC connection, auto sign on");
                dbConnection = ds.getConnection();
                deleteAll(dbConnection);
                System.out.println("Deleted all messages\n");
            }else if ("DELETE_ALL".equals(op)) {

            } else {
                //unsupported op
            }

        }finally{
            try{
                dbConnection.close();
            }catch(Exception ex){
                debug("Exception occured while closing database con nection.");
            }
        }
    }

    private void createRow(String id, String body,
            java.sql.Connection dbConnection)
        throws Exception {

        // Create row for this message
        debug("CreateRow with ID = " + id + ", BODY = " + body);
        Statement stmt = dbConnection.createStatement();
        String query = "INSERT INTO messages (messageId, message)" +
            "VALUES ('" + id + "', '" + body + "')";
        int resultCount = stmt.executeUpdate(query);
        if ( resultCount != 1 ) {
            throw new Exception(
                    "ERROR in INSERT !! resultCount = "+resultCount);
        }
        stmt.close();
    }

    private void deleteRow(String id, java.sql.Connection dbConnection)
        throws Exception {

        // Delete row for this message
        debug("DeleteRow with ID = " + id);
        Statement stmt = dbConnection.createStatement();
        String query = "DELETE FROM messages WHERE messageId = '" + id + "'";
        int resultCount = stmt.executeUpdate(query);
        if ( resultCount != 1 ) {
            throw new Exception(
                    "ERROR in INSERT !! resultCount = "+resultCount);
        }
        stmt.close();
    }

    private void deleteAll(java.sql.Connection dbConnection)
        throws Exception {

        // Delete row for this message
        Statement stmt = dbConnection.createStatement();
        String query = "DELETE FROM messages";
        int resultCount = stmt.executeUpdate(query);
        debug("Delete all rows from messages... count = " + resultCount);
        stmt.close();
    }

    private void debug(String msg) {
        System.out.println("[MyMessageBean] --> " + msg);
    }
}
