package faqapp;

import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

/**
 * AppSessionFacade Session Bean.
 **/
public class AppSessionFacadeBean implements SessionBean {
    /* ----------------------------------------
    * Begin business methods. The methods below
    * are called by the client code.
    * -------------------------------------- */

    /**
     * Method to create Area entity bean and return newly created areaID
     **/
    public int createArea(String areaDesc) {
        int areaID = 0;

        /* Create the Area EJB Local Object */
        try {
            AreaLocalHome areaHome = getAreaHome();
            AreaLocal area = areaHome.create(areaDesc);
            areaID = area.getAreaID().intValue();
        } catch (Exception e) {
            System.err.println("Error creating Area EJB Local Object: " + e.getMessage());
        }
        return areaID;
    }

    /**
     * Method to update Area entity bean
     **/
    public void updateArea(int areaID, String areaDesc) {
        try {
            /* Find the Area based on PK */
            AreaLocalHome areaHome = getAreaHome();
            AreaLocal area = areaHome.findByPrimaryKey(new Integer(areaID));

            /* Update Area */
            area.setAreaDesc(areaDesc);
        } catch (Exception e) {
            System.err.println("Error updating Area EJB Local Object: " + e.getMessage());
        }
    }

    /**
     * Method to find an Area by given areaID (PK)
     **/
    public AreaTO findAreaByPK(int areaID) {
        AreaLocal area = null;

        /* Find the Area based on PK */
        try {
            AreaLocalHome areaHome = getAreaHome();
            area = areaHome.findByPrimaryKey(new Integer(areaID));
        } catch (Exception e) {
            System.err.println("Error finding Area by PK: " + e.getMessage());
        }
        return createAreaTO(area);
    }

    /**
     * Method to find all Areas
     **/
    public AreaTO[] findAreaAll() {
        Collection areas = null;

        /* Find all Areas */
        try {
            AreaLocalHome areaHome = getAreaHome();
            areas = areaHome.findAll();
        } catch (Exception e) {
            System.err.println("Error finding all Areas: " + e.getMessage());
        }

        /* Create array of AreaTOs based on Areas */
        AreaTO[] areaTOs = new AreaTO[areas.size()];
        Iterator iter = areas.iterator();
        int areaCount = 0;
        while (iter.hasNext()) {
            areaTOs[areaCount] = createAreaTO((AreaLocal) iter.next());
            areaCount++;
        }
        return areaTOs;
    }

    /**
     * Method to create Topic entity bean and return newly created topicID
     **/
    public int createTopic(String topicDesc, int areaID) {
        int topicID = 0;

        /* Create the Topic EJB Local Object */
        try {
            /* Find the Area based on PK */
            AreaLocalHome areaHome = getAreaHome();
            AreaLocal area = areaHome.findByPrimaryKey(new Integer(areaID));
            TopicLocalHome topicHome = getTopicHome();
            TopicLocal topic = topicHome.create(topicDesc, area);
            topicID = topic.getTopicID().intValue();
        } catch (Exception e) {
            System.err.println("Error creating Topic EJB Local Object: " + e.getMessage());
        }
        return topicID;
    }

    /**
     * Method to update Topic entity bean
     **/
    public void updateTopic(int topicID, String topicDesc, int areaID) {
        try {
            /* Find the Topic based on PK */
            TopicLocalHome topicHome = getTopicHome();
            TopicLocal topic = topicHome.findByPrimaryKey(new Integer(topicID));

            /* Find the Area based on PK */
            AreaLocalHome areaHome = getAreaHome();
            AreaLocal area = areaHome.findByPrimaryKey(new Integer(areaID));

            /* Update Topic */
            topic.setTopicDesc(topicDesc);
            topic.setArea(area);
        } catch (Exception e) {
            System.err.println("Error updating Topic EJB Local Object: " + e.getMessage());
        }
    }

    /**
     * Method to find a TopicTO by given topicID (PK)
     **/
    public TopicTO findTopicByPK(int topicID) {
        TopicLocal topic = null;

        /* Find the Topic based on PK */
        try {
            TopicLocalHome topicHome = getTopicHome();
            topic = topicHome.findByPrimaryKey(new Integer(topicID));
        } catch (Exception e) {
            System.err.println("Error finding Topic by PK: " + e.getMessage());
        }
        return createTopicTO(topic);
    }

    /**
     * Method to find all Topics, returned as an Array of TopicTOs
     **/
    public TopicTO[] findTopicAll() {
        Collection topics = null;

        /* Find all Topics */
        try {
            TopicLocalHome topicHome = getTopicHome();
            topics = topicHome.findAll();
        } catch (Exception e) {
            System.err.println("Error finding all Topics: " + e.getMessage());
        }

        /* Create array of TopicTOs based on Topics */
        TopicTO[] topicTOs = new TopicTO[topics.size()];
        Iterator iter = topics.iterator();
        int topicCount = 0;
        while (iter.hasNext()) {
            topicTOs[topicCount] = createTopicTO((TopicLocal) iter.next());
            topicCount++;
        }
        return topicTOs;
    }

    /**
     * Method to find an Array of TopicTOs by given areaID
     **/
    public TopicTO[] findTopicsByAreaID(int areaID) {
        Collection topics = null;

        /* Find corresponding Topics */
        try {
            TopicLocalHome topicHome = getTopicHome();
            topics = topicHome.findByAreaID(new Integer(areaID));
        } catch (Exception e) {
            System.err.println("Error finding Topic by areaID: " + e.getMessage());
        }

        /* Create array of TopicTOs based on Topics */
        TopicTO[] topicTOs = new TopicTO[topics.size()];
        Iterator iter = topics.iterator();
        int topicCount = 0;
        while (iter.hasNext()) {
            topicTOs[topicCount] = createTopicTO((TopicLocal) iter.next());
            topicCount++;
        }
        return topicTOs;
    }

    /**
     * Method to create FAQ entity bean and return newly created questionID
     **/
    public int createFAQ(String question, String answer, boolean internalFlag, String productVersion, String createdBy, int[] areaIDs, int[] topicIDs) {
        int faqID = 0;
        String modifiedBy = null;
        Date modificationDate = null;

        /* Set creation date to be today's date */
        Date creationDate = new Date();

        /* Find corresponding Areas */
        Collection areas = findLocalAreas(areaIDs);

        /* Find corresponding Topics */
        Collection topics = findLocalTopics(topicIDs);
        try {
            /* Use the factory to create the FAQ EJB Local Object */
            FAQLocalHome faqHome = getFAQHome();
            FAQLocal faq = faqHome.create(question, answer, internalFlag, productVersion, createdBy, creationDate, modifiedBy, modificationDate, topics, areas);
            faqID = faq.getQuestionID().intValue();
        } catch (Exception e) {
            System.err.println("Error creating FAQ/FAQArea EJB Local Object: " + e.getMessage());
        }
        return faqID;
    }

    /**
     * Method to update FAQ entity bean
     **/
    public void updateFAQ(int questionID, String question, String answer, boolean internalFlag, String productVersion, String modifiedBy, int[] areaIDs, int[] topicIDs) {
        /* Set modification date to be today's date */
        Date modificationDate = new Date();

        try {
            /* Find the FAQ based on PK */
            FAQLocalHome faqHome = getFAQHome();
            FAQLocal faq = faqHome.findByPrimaryKey(new Integer(questionID));

            /* Find corresponding Areas */
            Collection areas = findLocalAreas(areaIDs);

            /* Find corresponding Topics */
            Collection topics = findLocalTopics(topicIDs);

            /* Update FAQ */
            faq.setQuestion(question);
            faq.setAnswer(answer);
            faq.setInternalFlag(internalFlag);
            faq.setProductVersion(productVersion);
            faq.setModifiedBy(modifiedBy);
            faq.setModificationDate(modificationDate);
            faq.setAreas(areas);
            faq.setTopics(topics);
        } catch (Exception e) {
            System.err.println("Error updating FAQ EJB Local Object: " + e.getMessage());
        }
    }

    /**
     * Method to find a FAQ by given questionID (PK)
     **/
    public FAQTO findFAQByPK(int questionID) {
        FAQTO faq = null;

        /* Find the FAQ based on PK */
        try {
            FAQLocalHome faqHome = getFAQHome();
            faq = createFAQTO(faqHome.findByPrimaryKey(new Integer(questionID)));
        } catch (Exception e) {
            System.err.println("Error finding FAQ by PK: " + e.getMessage());
        }
        return faq;
    }

    /**
     * Method to find an Array of FAQTOs by given areaID
     **/
    public FAQTO[] findFAQsByAreaID(int areaID) {
        Collection faqs = null;

        /* Find corresponding FAQs */
        try {
            FAQLocalHome faqHome = getFAQHome();
            faqs = faqHome.findByAreaID(new Integer(areaID));
        } catch (Exception e) {
            System.err.println("Error finding FAQ by areaID: " + e.getMessage());
        }

        /* Create array of FAQTOs based on FAQs */
        FAQTO[] faqTOs = new FAQTO[faqs.size()];
        Iterator iter = faqs.iterator();
        int faqCount = 0;
        while (iter.hasNext()) {
            faqTOs[faqCount] = createFAQTO((FAQLocal) iter.next());
            faqCount++;
        }
        return faqTOs;
    }

    /* ----------------------------------------
    * Begin private methods. The methods below
    * are used internally.
    * -------------------------------------- */

    /**
     * Private method to find Areas based on their PKs (areaIDs)
     **/
    private Collection findLocalAreas(int[] areaIDs) {
        Collection areas = new Vector();
        for (int i = 0; i < areaIDs.length; i++) {
            try {
                AreaLocalHome areaHome = getAreaHome();
                AreaLocal area = areaHome.findByPrimaryKey(new Integer(areaIDs[i]));
                areas.add(area);
            } catch (Exception e) {
                System.err.println("Error finding Area by areaID: " + e.getMessage());
            }
        }
        return (areas.size() > 0) ? areas : null;
    }

    /**
     * Private method to find a Topic by given topicID (PK)
     **/
    private Collection findLocalTopics(int[] topicIDs) {
        Collection topics = new Vector();
        for (int i = 0; i < topicIDs.length; i++) {
            try {
                TopicLocalHome topicHome = getTopicHome();
                TopicLocal topic = topicHome.findByPrimaryKey(new Integer(topicIDs[i]));
                topics.add(topic);
            } catch (Exception e) {
                System.err.println("Error finding Area by areaID: " + e.getMessage());
            }
        }
        return (topics.size() > 0) ? topics : null;
    }

    /**
     * Method to create AreaTO based on Area EJB
     **/
    private AreaTO createAreaTO(AreaLocal area) {
        Collection topics = area.getTopics();
        Iterator topicsIter = topics.iterator();
        int[] topicIDs = new int[topics.size()];
        int topicCount = 0;
        Collection faqs = area.getFaqs();
        Iterator faqsIter = faqs.iterator();
        int[] faqIDs = new int[faqs.size()];
        int faqCount = 0;
        while (topicsIter.hasNext()) {
            topicIDs[topicCount] = ((TopicLocal) topicsIter.next()).getTopicID().intValue();
            topicCount++;
        }
        while (faqsIter.hasNext()) {
            faqIDs[faqCount] = ((FAQLocal) faqsIter.next()).getQuestionID().intValue();
            faqCount++;
        }
        return new AreaTO(area.getAreaID().intValue(), area.getAreaDesc(), topicIDs, faqIDs);
    }

    /**
     * Method to create TopicTO based on Topic EJB
     **/
    private TopicTO createTopicTO(TopicLocal topic) {
        Collection faqs = topic.getFaqs();
        Iterator faqsIter = faqs.iterator();
        int[] faqIDs = new int[faqs.size()];
        int faqCount = 0;
        while (faqsIter.hasNext()) {
            faqIDs[faqCount] = ((FAQLocal) faqsIter.next()).getQuestionID().intValue();
            faqCount++;
        }
        return new TopicTO(topic.getTopicID().intValue(), topic.getTopicDesc(), topic.getArea().getAreaID().intValue(), faqIDs);
    }

    /**
     * Method to create FAQTO based on FAQ EJB
     **/
    private FAQTO createFAQTO(FAQLocal faq) {
        Collection topics = faq.getTopics();
        Iterator topicsIter = topics.iterator();
        int[] topicIDs = new int[topics.size()];
        int topicCount = 0;
        Collection areas = faq.getAreas();
        Iterator areasIter = areas.iterator();
        int[] areaIDs = new int[areas.size()];
        int areaCount = 0;
        while (topicsIter.hasNext()) {
            topicIDs[topicCount] = ((TopicLocal) topicsIter.next()).getTopicID().intValue();
            topicCount++;
        }
        while (areasIter.hasNext()) {
            areaIDs[areaCount] = ((AreaLocal) areasIter.next()).getAreaID().intValue();
            areaCount++;
        }
        return new FAQTO(faq.getQuestionID().intValue(), faq.getQuestion(), faq.getAnswer(), faq.getInternalFlag(), faq.getProductVersion(), faq.getCreatedBy(), faq.getCreationDate(), faq.getModifiedBy(), faq.getModificationDate(), topicIDs, areaIDs);
    }

    /**
     * Method to lookup Area Local Home Object
     **/
    private AreaLocalHome getAreaHome() throws NamingException {
        AreaLocalHome areaHome = null;

        /* Get a reference to the Area Local Home Object -
           the factory for Area EJB Local Object */
        try {
            InitialContext ic = new InitialContext();
            Object objref = ic.lookup("java:comp/env/ejb/AreaLocalHome");
            areaHome = (AreaLocalHome) PortableRemoteObject.narrow(objref, AreaLocalHome.class);
        } catch (Exception e) {
            System.err.println("Error looking up Area Local Home Object: " + e.getMessage());
        }
        return areaHome;
    }

    /**
     * Method to lookup Topic Local Home Object
     **/
    private TopicLocalHome getTopicHome() throws NamingException {
        TopicLocalHome topicHome = null;

        /* Get a reference to the Topic Local Home Object -
           the factory for Topic EJB Local Object */
        try {
            InitialContext ic = new InitialContext();
            Object objref = ic.lookup("java:comp/env/ejb/TopicLocalHome");
            topicHome = (TopicLocalHome) PortableRemoteObject.narrow(objref, TopicLocalHome.class);
        } catch (Exception e) {
            System.err.println("Error looking up Topic Local Home Object: " + e.getMessage());
        }
        return topicHome;
    }

    /**
     * Method to lookup FAQ Local Home Object
     **/
    private FAQLocalHome getFAQHome() throws NamingException {
        FAQLocalHome faqHome = null;

        /* Get a reference to the FAQ Local Home Object -
           the factory for FAQ EJB Local Object */
        try {
            InitialContext ic = new InitialContext();
            Object objref = ic.lookup("java:comp/env/ejb/FAQLocalHome");
            faqHome = (FAQLocalHome) PortableRemoteObject.narrow(objref, FAQLocalHome.class);
        } catch (Exception e) {
            System.err.println("Error looking up FAQ Local Home Object: " + e.getMessage());
        }
        return faqHome;
    }

    /* ------------------------------------------------------
    * Begin EJB-required methods. The methods below are called
    * by the container, and never called by client code.
    * ------------------------------------------------------- */

    public void setSessionContext(SessionContext ctx) {
    }

    public void ejbActivate() {
    }

    public void ejbPassivate() {
    }

    public void ejbCreate() {
    }

    public void ejbRemove() {
    }
}
