package com.oreilly.jent.transactions.servlets;

/**
 * In general, you may use the code in this book in your programs and 
 * documentation. You do not need to contact us for permission unless 
 * you're reproducing a significant portion of the code. For example, 
 * writing a program that uses several chunks of code from this book does 
 * not require permission. Selling or distributing a CD-ROM of examples 
 * from O'Reilly books does require permission. Answering a question by 
 * citing this book and quoting example code does not require permission. 
 * Incorporating a significant amount of example code from this book into 
 * your product's documentation does require permission.
 * 
 * We appreciate, but do not require, attribution. An attribution usually 
 * includes the title, author, publisher, and ISBN. For example: 
 * 
 *   "Java Enterprise in a Nutshell, Third Edition, 
 *    by Jim Farley and William Crawford 
 *    with Prakash Malani, John G. Norman, and Justin Gehtland. 
 *    Copyright 2006 O'Reilly Media, Inc., 0-596-10142-2."
 *  
 *  If you feel your use of code examples falls outside fair use or the 
 *  permission given above, feel free to contact us at 
 *  permissions@oreilly.com.
 */

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;

import com.oreilly.jent.transactions.bmtd.ManagerBMTD;
import com.oreilly.jent.transactions.bmtd.ManagerBMTDHome;
import com.oreilly.jent.transactions.cmtd.ManagerCMTD;
import com.oreilly.jent.transactions.cmtd.ManagerCMTDHome;
import com.oreilly.jent.transactions.domain.Person;
import com.oreilly.jent.transactions.domain.PersonHome;
import com.oreilly.jent.transactions.domain.PersonStatusValue;
import com.oreilly.jent.transactions.domain.PersonValue;

public class PersonEditServlet extends HttpServlet {
    protected static Logger sLogger = Logger.getLogger(PersonEditServlet.class.getName());
    protected static Map aCommandMap = new HashMap();

    interface Command {
        public Object execute(
            HttpServletRequest aHttpServletRequest,
            HttpServletResponse aHttpServletResponse
        ) throws Exception;
    }

    class DirectCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);
            InitialContext aInitialContext = new InitialContext();
            PersonHome aPersonHome = (PersonHome) aInitialContext.lookup("java:comp/env/ejb/Person");
            Person p = aPersonHome.create(aPersonValue.getEmail(), aPersonValue.getPassword());
            p.setWorkPhone(aPersonValue.getWorkPhone());
            p.setHomePhone(aPersonValue.getHomePhone());

            sLogger.info("Created a person with id : " + p.getPersonId());
            return null;
        }
    }

    class CMTDCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            sLogger.info("1 executing cmtd command...");
            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);
            InitialContext aInitialContext = new InitialContext();
            ManagerCMTDHome aManagerCMTDHome =
                (ManagerCMTDHome) aInitialContext.lookup("java:comp/env/ejb/ManagerCMTD");
            ManagerCMTD aManagerCMTD = aManagerCMTDHome.create();
            aPersonValue = aManagerCMTD.createPersonNewTransaction(aPersonValue);

            sLogger.info(" created a person with id : " + aPersonValue.getPersonId());
            return null;
        }
    }

    class BMTDCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            sLogger.info("executing bmtd command...");
            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);
            InitialContext aInitialContext = new InitialContext();
            ManagerBMTDHome aManagerBMTDHome =
                (ManagerBMTDHome) aInitialContext.lookup("java:comp/env/ejb/ManagerBMTD");
            ManagerBMTD aManagerBMTD = aManagerBMTDHome.create();
            aPersonValue = aManagerBMTD.createPerson(aPersonValue);

            sLogger.info(" created a person with id : " + aPersonValue.getPersonId());
            return null;
        }
    }

    class ClientCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            sLogger.info("executing client command...");

            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);

            InitialContext aInitialContext = new InitialContext();
            UserTransaction aUserTransaction = (UserTransaction)
                aInitialContext.lookup("java:comp/UserTransaction");
            try {
                aUserTransaction.begin();

                PersonHome aPersonHome = 
                    (PersonHome) aInitialContext.lookup("java:comp/env/ejb/Person");
                Person p = aPersonHome.create(aPersonValue.getEmail(), 
                                              aPersonValue.getPassword());
                p.setWorkPhone(aPersonValue.getWorkPhone());
                p.setHomePhone(aPersonValue.getHomePhone());

                sLogger.info(" created a person with id : " + p.getPersonId());
                aUserTransaction.commit();
            } catch (Exception e) {
                try {
                    aUserTransaction.rollback();
                } catch (Exception aException) {
                    String aMessage = "Exception occured in client command.execute transaction rollback";
                    sLogger.log(Level.SEVERE, aMessage, aException);
                    throw aException;
                }
                String aMessage = "Exception occured in client command.execute ";
                sLogger.log(Level.SEVERE, aMessage, e);
                throw e;
            }
            return null;
        }
    }

    class RequiredCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            sLogger.info("executing required command...");
            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);
            PersonStatusValue aPersonStatusValue = getPersonStatusValue(aHttpServletRequest);

            InitialContext aInitialContext = new InitialContext();
            ManagerCMTDHome aManagerCMTDHome =
                (ManagerCMTDHome) aInitialContext.lookup("java:comp/env/ejb/ManagerCMTD");
            ManagerCMTD aManagerCMTD = aManagerCMTDHome.create();
            aPersonValue = aManagerCMTD.createPersonAndStatus(aPersonValue, aPersonStatusValue);

            sLogger.info(" required created a person with id : " + aPersonValue.getPersonId());
            return null;
        }
    }

    class RequiresNewCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            sLogger.info("executing requires new command...");
            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);
            PersonStatusValue aPersonStatusValue = getPersonStatusValue(aHttpServletRequest);

            InitialContext aInitialContext = new InitialContext();
            ManagerCMTDHome aManagerCMTDHome =
                (ManagerCMTDHome) aInitialContext.lookup("java:comp/env/ejb/ManagerCMTD");
            ManagerCMTD aManagerCMTD = aManagerCMTDHome.create();
            aPersonValue = aManagerCMTD.createPersonAndStatusNew(aPersonValue, aPersonStatusValue);

            sLogger.info(" required created a person with id : " + aPersonValue.getPersonId());
            return null;
        }
    }

    class MessageCommand implements Command {
        public Object execute(HttpServletRequest aHttpServletRequest, HttpServletResponse aHttpServletResponse) throws Exception {
            sLogger.info("executing message command...");
            PersonValue aPersonValue = getPersonValue(aHttpServletRequest);

            InitialContext aInitialContext = new InitialContext();
            ConnectionFactory aConnectionFactory
                = (ConnectionFactory) aInitialContext.lookup("java:comp/env/jms/semJMSConnectionFactory");
            Destination aDestination
                = (Destination) aInitialContext.lookup("java:comp/env/jms/semPersonQueue");

            Connection aConnection = null;
            Session aSession = null;
            MessageProducer aMessageProducer = null;

            try {
                aConnection = aConnectionFactory.createConnection();
                aSession = aConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                aMessageProducer = aSession.createProducer(aDestination);
                Message aMessage = aSession.createObjectMessage(aPersonValue);
                aMessageProducer.send(aMessage);
            } finally {
                if (aMessageProducer != null) aMessageProducer.close();
                if (aSession != null) aSession.close();
                if (aConnection != null) aConnection.close();
            }
            return null;
        }
    }

    public void init() throws ServletException {
        super.init();
        aCommandMap.put("direct", new DirectCommand());
        aCommandMap.put("cmtd", new CMTDCommand());
        aCommandMap.put("bmtd", new BMTDCommand());
        aCommandMap.put("client", new ClientCommand());
        aCommandMap.put("required", new RequiredCommand());
        aCommandMap.put("new", new RequiresNewCommand());
        aCommandMap.put("message", new MessageCommand());
    }

    protected PersonStatusValue getPersonStatusValue(HttpServletRequest aHttpServletRequest) {
        String aStatus = aHttpServletRequest.getParameter("status");
        String aStatusComment = aHttpServletRequest.getParameter("statusComment");

        PersonStatusValue aPersonStatusValue = new PersonStatusValue();
        aPersonStatusValue.setStatus(aStatus);
        aPersonStatusValue.setStatusComment(aStatusComment);

        return aPersonStatusValue;
    }

    protected PersonValue getPersonValue(HttpServletRequest aHttpServletRequest) {
        String aEmail = aHttpServletRequest.getParameter("email");
        String aPassword = aHttpServletRequest.getParameter("password");
        String aWorkPhone = aHttpServletRequest.getParameter("workPhone");
        String aHomePhone = aHttpServletRequest.getParameter("homePhone");

        PersonValue aPersonValue = new PersonValue();
        aPersonValue.setEmail(aEmail);
//        aPersonValue.setFAX();
        aPersonValue.setHomePhone(aHomePhone);
        aPersonValue.setPassword(aPassword);
//        aPersonValue.setPersonId();
        aPersonValue.setWorkPhone(aWorkPhone);

        sLogger.info(
            "1 email is: " + aEmail
            + " password is " + aPassword
            + " work phone is " + aWorkPhone
            + " home phone is " + aHomePhone
        );

        return aPersonValue;
    }

    protected void doPost(
        HttpServletRequest aHttpServletRequest,
        HttpServletResponse aHttpServletResponse
    ) throws ServletException, IOException {
        String aType = aHttpServletRequest.getParameter("transactionType");
        try {
            Command aCommand = (Command) aCommandMap.get(aType);
            if (aCommand != null) {
                aCommand.execute(aHttpServletRequest, aHttpServletResponse);
            } else {
                sLogger.warning("suitable command not found!!!");
            }
        } catch (Exception e) {
            String aMessage = "Exception occured in PersonEditServlet";
            sLogger.log(Level.SEVERE, aMessage, e);
            throw new ServletException(aMessage, e);
        }

        aHttpServletResponse.sendRedirect("index.jsp");
    }
}

