package cmp.mbrc.retailer.pagehandler;

import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import java.util.Vector;

import atg.servlet.DynamoHttpServletRequest;
import atg.servlet.DynamoHttpServletResponse;
import atg.droplet.DropletException;

import cmp.mbrc.retailer.pagehandler.GenericPageHandler;
import cmp.mbrc.retailer.State;
import cmp.mbrc.retailer.DbConfig;
import cmp.mbrc.retailer.Faq;
import cmp.mbrc.retailer.Image;
import cmp.mbrc.retailer.ImageValue;
import cmp.mbrc.retailer.Retailer;
import cmp.mbrc.retailer.ErrorMessages;
import cmp.mbrc.retailer.db.BooleanInd;
import cmp.mbrc.retailer.db.FaqSection;

/**
 * <p>
 * This class is the Dynamo Bean that is used with the JHTML page
 * that deals with the Service & Parts Frequently Asked Questions.
 *
 * <p>
 * Every <i>public</i> method in this class capture errors and displays
 * appropriate error messages. All droplet exceptions generate an error
 * message that is customizable by a jhtml programmer. In addition to
 * setting the error message of each droplet exception, an error code must
 * also be provided. The jhtml programmer can customize these error messages
 * by setting values to each error code using the message table property of the
 * component used to generate error messages. (For example, ErrorMessageForEach...)

 * Copyright:   Copyright (c) 2001
 * Company:     Critical Mass
 *
 * @author      Bonnie Ting
 * @version     $Revision: 1.3 $
 *
 * <p><b>
 * Last Modified By:</b> $Author: bonniet $ : $Date: 2001/01/29 17:45:21 $
 *
 * @todo: Change all the System.out to write to the log files -- BYT
 */

public class FaqServiceParts extends GenericPageHandler {


    /**
     * This constant is used for debugging a 'live' environment.
     * It returns information to positely identify the version of the class instance.
     * The string is automatically updated by CVS.
     */
    public static final String CVS_HEADER = "$Header: s:\\cvs/dev/mbretailer/retailer/src/cmp/mbrc/retailer/pagehandler/FaqServiceParts.java,v 1.3 2001/01/29 17:45:21 bonniet Exp $ : TAG $Name:  $";


    /**
     * Constructor
     */
    public FaqServiceParts() {
    }


    /**
     * Properties
     */

    // This property is used as an indicator for getting content from the database only
    // once until a persistence is done.
    private boolean mGetFaqFromDb = false;
    private boolean mGetMainImgFromDb = false;
    private boolean mGetMainImgValueFromDb = false;


    // property currState
    State mCurrState;
    public State getCurrState () {
        return mCurrState;
    }
    public void setCurrState (State pCurrState) {
        mCurrState = pCurrState;
    }

    // property allFaqBySection
    Vector mAllFaqBySection = new Vector();
    /**
     * This method gets all the frequently asked questions from the database for a specified
     * mb center and section.
     *
     * @return  Vector
     */
    public Vector getAllFaqBySection()
    {
       int mbCtrCode = getCurrRetailer().getMbCenterId();

        try
        {

            writeDebug("getAllFaqBySection(): Start");

            // The faqs are retrieved from the database only once.
            // NO further read from the dB until a persistence is done
            if (!mGetFaqFromDb) {

                writeDebug("Got faqs from database.");
                mAllFaqBySection = Faq.getAllFaqBySection(mbCtrCode, FaqSection.SERVICE_PARTS);
                this.addAll(mAllFaqBySection);

                mGetFaqFromDb = true;
            }
            writeDebug(getClassName() + ": getAllFaqBySection: End.");
        }
        catch (SQLException e)
        {
            this.handleFormError(e, "getAllFaqBySection()");
        }

        return mAllFaqBySection;
    }
    public void setAllFaqBySection (Vector pAllFaqBySection) {
        if (mAllFaqBySection != pAllFaqBySection) {
            mAllFaqBySection = pAllFaqBySection;
        }
    }

    // property currFaqId
    int mCurrFaqId;
    public int getCurrFaqId () {
        return mCurrFaqId;
    }
    /**
     * Override this method so that the currFaq object refers to the Faq with
     * the given id.
     *
     * @param   pCurrFaqId
     */
    public void setCurrFaqId (int pCurrFaqId) {
        Faq currFaq = null;
        mCurrFaqId = pCurrFaqId;

        // Look in the allFaq and find the current faq using the given id
        for (int i=0; i < mAllFaqBySection.size(); i++) {
            currFaq = (Faq) mAllFaqBySection.get(i);
            if (currFaq.getId() == pCurrFaqId) {
                mCurrFaq = currFaq;
                break;
            }
            currFaq = null;
        }
        if (currFaq == null) mCurrFaq = new Faq();
    }

    // property currFaq
    Faq mCurrFaq;
    public Faq getCurrFaq () {
        return mCurrFaq;
    }
    public void setCurrFaq (Faq pCurrFaq) {
        mCurrFaq = pCurrFaq;
    }

    // property id
    // This property is set by jhtml when a user wants to retrieve a certain faq identified
    // by id
    int mId;
    public int getId () {
        return mId;
    }
    public void setId (int pId) {
        mId = pId;
    }


    // property mainImg
    Image mMainImg;
    public Image getMainImg () {
        try
        {

            writeDebug("getMainImg(): Start");

            // The faqs are retrieved from the database only once.
            // NO further read from the dB until a persistence is done
            if (!mGetMainImgFromDb) {

                writeDebug("Got image from database.");
                // todo: the main image name is hard-coded. This needs to be updated
                mMainImg = Image.getImage(cmp.mbrc.retailer.db.ServiceParts.FAQ_SERVICE_PARTS, "main");

                // Add to the collection of all Retailer Content for this class
                // found in the GenericPageHandler
                this.insertContent(mMainImg);

                mGetMainImgFromDb = true;
            }
            writeDebug(getClassName() + ": getMainImg: End.");
        }
        catch (SQLException e)
        {
            this.handleFormError(e, "getMainImg()");
        }

        return mMainImg;
    }
    public void setMainImg (Image pMainImg) {
        mMainImg = pMainImg;
    }


    // property mainImgValue
    ImageValue mMainImgValue;
    public ImageValue getMainImgValue () {

       int mbCtrCode = getCurrRetailer().getMbCenterId();

        try
        {

            writeDebug("getMainImgValue(): Start");

            // The faqs are retrieved from the database only once.
            // NO further read from the dB until a persistence is done
            if (!mGetMainImgValueFromDb) {

                // todo: the main image name is hard-coded. This needs to be updated
                mMainImgValue = ImageValue.getImageValue(cmp.mbrc.retailer.db.ServiceParts.FAQ_SERVICE_PARTS, "main", mbCtrCode);

                // Add to the collection of all Retailer Content for this class
                // found in the GenericPageHandler
                this.insertContent(mMainImgValue);

                mGetMainImgValueFromDb = true;
            }
            writeDebug(getClassName() + ": getMainImgValue: End.");
        }
        catch (SQLException e)
        {
            this.handleFormError(e, "getMainImgValue()");
        }

        return mMainImgValue;
    }
    public void setMainImgValue (ImageValue pMainImgValue) {
        mMainImgValue = pMainImgValue;
    }



    /**
     * This method returns the class name of this object.
     *
     * @return  String: the name of the class
     */
    private String getClassName() {
        return this.getClass().getName();
    }


    /**
     * This method will write the incoming debug statement to the log writer.
     *
     * todo: change System.out.println to use the LogWriter -- BYT
     */
    private void writeDebug(String pDebugStmt)
    {
        if (DbConfig.getDebug().getSrvFaqFlag()) {
            System.out.println(getClassName() + ": " + pDebugStmt);
        }
    }


    /**
     * Method used to return the current retailer object
     *
     * @return   Retailer
     */
    private Retailer getCurrRetailer()
    {
        return mCurrState.getCurrentRetailer();
    }


    /**
     * This method returns the next number for sequence in creating
     * a new faq.
     */
    private int getNextSeq () {
        return mAllFaqBySection.size() + 1;
    }


    /**
     * This method creates a new faq in the database.
     * The SQL and DropletExceptions are passed to handleFormError, all other
     * errors are handled by the Dynamo error html page.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleCreateFaq(DynamoHttpServletRequest pRequest,
                                   DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.

        try
        {
            writeDebug("handleCreateFaq: Start");

            // Set the default values for creating an faq
            mCurrFaq.setMbCenterId(getCurrRetailer().getMbCenterId());
            mCurrFaq.setSequence(getNextSeq());
            mCurrFaq.setIndVisible(BooleanInd.YES);
            mCurrFaq.setLastModified(getSQLDate());

            // Flag this Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            mCurrFaq.setModified(true);

            // Validate this new Faq
            mCurrFaq.validateCreate();

            // If there is an error found with validating this Faq, the primary key
            // will not be set until the validation is clean
            mCurrFaq.setId(DbConfig.getUniqueKey());

            // Add to this classes collection of faqs
            mAllFaqBySection.add(mCurrFaq);

            // Add to the collection of all Retailer Content for this class
            // found in the GenericPageHandler
            this.insertContent(mCurrFaq);

            writeDebug("handleCreateFaq: End.");
        }
        catch (DropletException e)
        {
            this.handleFormError(e, "handleCreateFaq()");
        }

        return returnValue;
    }


    /**
     * This method updates an existing faq.
     * The SQL and DropletExceptions are passed to handleFormError, all other
     * errors are handled by the Dynamo error html page.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleUpdateFaq(DynamoHttpServletRequest pRequest,
                                   DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.

        try
        {
            writeDebug("handleUpdateFaq: Start");

            // Validate this updated Faq
            mCurrFaq.validateUpdate();

            // Set the default values for updating an faq
            mCurrFaq.setLastModified(getSQLDate());

            // Flag this Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            mCurrFaq.setModified(true);

            writeDebug("handleUpdateFaq: End");
        }
        catch (DropletException e)
        {
            this.handleFormError(e, "handleUpdateFaq()");
        }

        return returnValue;
    }


    /**
     * This method deletes an faq from the database.
     * The SQL and DropletExceptions are passed to handleFormError, all other
     * errors are handled by the Dynamo error html page.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleDeleteFaq(DynamoHttpServletRequest pRequest,
                                   DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.
        Faq faqToDelete = null;

        try
        {
            writeDebug("handleDeleteFaq(): Start");

            // Delete the current faq from the collection of faqs of this class
            deleteFaq();

            // Validate this Faq to delete
            mCurrFaq.validateDelete();

            // Add this Faq to the collection of deleted Retailer Content of
            // the GenericPageHandler
            deleteContent(mCurrFaq);

            mCurrFaq = null;

            writeDebug("handleDeleteFaq(): Deleted.");
            writeDebug("handleDeleteFaq(): End");
        }
        catch (DropletException e)
        {
            this.handleFormError(e, "handleDeleteFaq()");
        }

        return returnValue;
    }


    /**
     * This method will delete the current faq from the collection of faqs of this class
     */
    private void deleteFaq()
    {
        int currIndex = mAllFaqBySection.indexOf(mCurrFaq);
        mAllFaqBySection.remove(currIndex);
        reorderSeq(currIndex);
    }


    /**
     * This method will alter the sequence of all the other Faqs after the faq that is deleted.
     *
     * @param   beginIndex: the starting index of where to begin reordering sequence
     */
    private void reorderSeq(int beginIndex) {
        Faq currFaq = null;
        int currSeq = 0;

        for (int i=beginIndex; i<mAllFaqBySection.size(); i++) {
            currFaq = (Faq)mAllFaqBySection.get(i);
            currSeq = currFaq.getSequence();
            currFaq.setSequence(--currSeq);
            currFaq.setModified(true);
        }

    }


    /**
     * This method will take the currently selected faq and make it visible.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleTurnOnFaq(DynamoHttpServletRequest pRequest,
                                   DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.

        writeDebug("handleTurnOnFaq(): Start");
        writeDebug("handleTurnOnFaq(): CurrFaqId: " + mCurrFaqId);


        // Check to make sure there is an faq selected
        if (mCurrFaqId != 0) {
            // Get the selected "off" faq and turn it "on"
            mCurrFaq.setIndVisible(BooleanInd.YES);

            // Flag this Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            mCurrFaq.setModified(true);

            // Reset the current faq id and object for jhtml
            mCurrFaqId = 0;
            mCurrFaq = null;
        }

        writeDebug("handleTurnOnFaq(): End");

        return returnValue;
    }


    /**
     * This method will take the currently selected faq and make it non-visible.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleTurnOffFaq(DynamoHttpServletRequest pRequest,
                                    DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.

        writeDebug("handleTurnOffFaq(): Start");
        writeDebug("handleTurnOnFaq(): CurrFaqId: " + mCurrFaqId);

        // Check to make sure there is an faq selected
        if (mCurrFaqId != 0) {
            // Get the selected "on" faq and turn it "off"
            mCurrFaq.setIndVisible(BooleanInd.NO);

            // Flag this Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            mCurrFaq.setModified(true);

            // Reset the current faq id and object for jhtml
            mCurrFaqId = 0;
            mCurrFaq = null;
        }

        writeDebug("handleTurnOffFaq(): End");

        return returnValue;
    }


    /**
     * This method will take the currently selected faq and move the sequence up one.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleSequenceUp(DynamoHttpServletRequest pRequest,
                                    DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.

        writeDebug("handleSequenceUp(): Start");
        writeDebug("handleTurnOnFaq(): CurrFaqId: " + mCurrFaqId);

        // Check to make sure there is an faq selected
        if (mCurrFaqId != 0) {
            shiftSeqUp();

            // Reset the current faq id and object for jhtml
            mCurrFaqId = 0;
            mCurrFaq = null;
        }

        writeDebug("handleSequenceUp(): End");

        return returnValue;
    }


    /**
     * This method will take the currently selected faq and move the sequence down one.
     *
     * @param       pRequest: dynamo request object
     * @param       pResponce: dynamo response object
     *
     * @exception   ServletException
     * @exception   IOException
     *
     * @return      boolean: set to false if the servlet is redirected
     */
    public boolean handleSequenceDown(DynamoHttpServletRequest pRequest,
                                      DynamoHttpServletResponse pResponse)
    throws ServletException, IOException
    {
        boolean returnValue = true; // ONLY set to false if Servlet is Redirected.

        writeDebug("handleSequenceDown(): Start");
        writeDebug("handleTurnOnFaq(): CurrFaqId: " + mCurrFaqId);

        // Check to make sure there is an faq selected
        if (mCurrFaqId != 0) {
            shiftSeqDown();

            // Reset the current faq id and object for jhtml
            mCurrFaqId = 0;
            mCurrFaq = null;
        }

        writeDebug("handleSequenceDown(): End");

        return returnValue;
    }


    /**
     * This method shifts the currFaq's sequence up one and correspondingly alters
     * the Vector of all faqs of this class.
     */
    private void shiftSeqUp() {

        Faq prevFaq = null;
        int currSeq = 0;
        int prevSeq = 0;
        int curr=0;
        int prev=0;

        // Find the index of the current faq
        curr = mAllFaqBySection.indexOf(mCurrFaq);

        // Check to make sure that the current faq is not already the first in sequence
        if (curr != 0) {
            prev = curr - 1;

            // Move the sequence of this Faq up one position
            currSeq = mCurrFaq.getSequence();
            mCurrFaq.setSequence(currSeq-1);
            // Flag this Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            mCurrFaq.setModified(true);

            // Move the sequence of the previous Faq down one position
            prevFaq = (Faq)mAllFaqBySection.get(prev);
            prevSeq = prevFaq.getSequence();
            prevFaq.setSequence(prevSeq+1);
            // Flag the other Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            prevFaq.setModified(true);

            // Swap the previous element with the current
            swap(curr, prev);
        }
    }


    /**
     * This method shifts the currFaq's sequence down one and correspondingly alters
     * the Vector of all faqs of this class.
     */
    private void shiftSeqDown() {

        Faq nextFaq = null;
        int currSeq = 0;
        int nextSeq = 0;
        int curr=0;
        int next=0;

        // Find the index of the current faq
        curr = mAllFaqBySection.indexOf(mCurrFaq);

        // Check to make sure that the current faq is not already the last in sequence
        if (curr != mAllFaqBySection.size()-1) {
            next = curr + 1;

            // Move the sequence of this Faq down one position
            currSeq = mCurrFaq.getSequence();
            mCurrFaq.setSequence(currSeq+1);
            // Flag this Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            mCurrFaq.setModified(true);

            // Move the sequence of the next Faq up one position
            nextFaq = (Faq)mAllFaqBySection.get(next);
            nextSeq = nextFaq.getSequence();
            nextFaq.setSequence(nextSeq-1);
            // Flag the other Faq as being modified so the GenericPageHandler knows to save this
            // RetailerContent to the dB
            nextFaq.setModified(true);

            // Swap the next element with the current
            swap(curr, next);
        }
    }


    /**
     * This method swaps the two objects at the given indices for the Vector of all faqs.
     * i.e. Object at position a will be moved to position b and object b to position a.
     *
     * todo: Abstract this method to be more general and move to a utility package?? -- BYT
     */
    private void swap(int a, int b) {
        Faq temp;

        // Save the object at position a
        temp = (Faq)mAllFaqBySection.remove(a);

        // Move the object at position a to position b
        mAllFaqBySection.add(b,temp);
    }


    /**
     * This method saves all the properties that need to be persisted to the database.
     * <p>NOTE: Each time a new database property is added to this class, this method must be
     * modified as well.
     *
     * @param   pRequest: dynamo request object
     * @param   pResponce: dynamo response object
     *
     * @exception SQLException
     */
    public boolean handlePersistToDb(DynamoHttpServletRequest pRequest,
                                     DynamoHttpServletResponse pResponse)
    throws SQLException
    {
        boolean returnValue = true; // set to false if the servlet is redirected

        try
        {
            writeDebug("persistToDb(): Start");

            // Persist to the database by calling the save method of the GenericPageHandler
            // which will save all of the RetailerContent for this class
            this.save();

            // Reset this flag so the next time faqs are grabbed from the database
            mGetFaqFromDb = false;

            // Reset these flags so the next time main images is grabbed from the database
            mGetMainImgFromDb = false;
            mGetMainImgValueFromDb = false;

            writeDebug("persistToDb(): End");
        }
        catch (SQLException e)
        {
            this.handleFormError(e, "persistToDb()");
        }

        return returnValue;
    }




}


1