/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package com.queplix.qwoss.inbox.ejb;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.modules.attachment.ejb.AttachmentManagerLocal;
import com.queplix.core.modules.attachment.ejb.AttachmentManagerLocalHome;
import com.queplix.core.modules.config.utils.SysPropertyManager;
import com.queplix.core.modules.eql.ejb.EQLManagerLocal;
import com.queplix.core.modules.eql.ejb.EQLManagerLocalHome;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.inbox.InboxHelper;
import com.queplix.core.modules.inbox.InboxMessage;
import com.queplix.core.modules.inbox.utils.log.InboxLogPublisher;
import com.queplix.core.modules.jeo.JEObjectHandler;
import com.queplix.core.modules.jeo.ejb.JEOManagerLocal;
import com.queplix.core.modules.jeo.gen.AttachmentTempObject;
import com.queplix.core.utils.DateHelper;
import com.queplix.core.utils.JNDINames;
import com.queplix.core.utils.StringHelper;
import com.queplix.core.utils.cache.CacheObjectManager;
import com.queplix.qwoss.gen.CustomerObject;
import com.queplix.qwoss.gen.CustomerObjectHandler;
import com.queplix.qwoss.gen.EmployeeObjectHandler;
import com.queplix.qwoss.gen.InteractionObject;
import com.queplix.qwoss.gen.InteractionObjectHandler;
import com.queplix.qwoss.gen.InteractionTicketObject;
import com.queplix.qwoss.gen.InteractionTicketObjectHandler;
import com.queplix.qwoss.gen.TicketMailObject;
import com.queplix.qwoss.gen.TicketMailObjectHandler;
import com.queplix.qwoss.inbox.CustomInboxHelper;
import com.queplix.qwoss.utils.ApplicationHelper;

import java.util.Properties;

/**
 * The Inbox Manager EJB.
 *
 * @author Konstantin Mironov
 * @since 8 Dec 2006
 */
public class InboxManagerEJB
        extends com.queplix.core.modules.inbox.ejb.InboxManagerEJB {

    // ------------------------------------------------------- Public methods

    /**
     * The method creates a ticket by the message.
     *
     * @param ls           logon session object
     * @param inboxMessage message object
     * @return true
     */
    public boolean createTicket(LogonSession ls, InboxMessage inboxMessage) {

        INFO("Create a new ticket by the message...");
        long time = System.currentTimeMillis();
        Exception error = null;
        Long ticketID = null;

        JEOManagerLocal jeoManager = getJEOManager();

        // Save!
        try {

            // check is the customer has already got
            if(inboxMessage.getSenderID() == null) {
                Long customerID = getCustomer(ls, inboxMessage);
                if(customerID == null) {
                    // try to get the default customer
                    String emailDefaulCustomer = SysPropertyManager.getProperty(
                            "IN_EMAIL_DEFAULT_CUSTOMER_ID");
                    if(emailDefaulCustomer != null) {
                        inboxMessage.setSenderID(new Long(emailDefaulCustomer));
                        inboxMessage.setSenderType(
                                CustomInboxHelper.CUSTOMER_TYPE);
                    } else {
                        // the ticket isn't linked
                        throw new NullPointerException(
                                "The system property IN_EMAIL_DEFAULT_CUSTOMER_ID wasn't found.");
                    } // if (emailDefaulCustomer != null)
                } // if (customerID != null)
            } // if (inboxMessage.getSenderID() == null)

            Long interactionId = null;
            if(inboxMessage.getObjectId() != null &&
                    inboxMessage.getObjectType() == ApplicationHelper
                            .INTERACTION_OBJECT_TYPE) {
                interactionId = inboxMessage.getObjectId();
            }

            JEObjectHandler hnd = jeoManager.create(ls,
                    TicketMailObjectHandler.class);
            TicketMailObject ticketObj = (TicketMailObject) hnd.getJEObject();
            // set status
            String defaultTicketStatus = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_STATUS");
            if(defaultTicketStatus == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_STATUS wasn't found.");
            }
            ticketObj.setQw_status(new Integer(defaultTicketStatus));
            // set priority
            String defaultTicketPriority = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_PRIORITY");
            if(defaultTicketPriority == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_PRIORITY wasn't found.");
            }
            ticketObj.setQw_priority(new Integer(defaultTicketPriority));
            // set type
            String defaultTicketType = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_TYPE");
            if(defaultTicketType == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_TYPE wasn't found.");
            }
            ticketObj.setQw_type(new Integer(defaultTicketType));
            // set source
            String defaultTicketSource = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_SOURCE");
            if(defaultTicketSource == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_SOURCE wasn't found.");
            }
            ticketObj.setQw_source(new Integer(defaultTicketSource));
            // set impact
            String defaultTicketImpact = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_IMPACT");
            if(defaultTicketImpact == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_IMPACT wasn't found.");
            }
            ticketObj.setQw_impact(new Integer(defaultTicketImpact));
            // set agent
            String defaultTicketAgent = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_AGENT");
            if(defaultTicketAgent == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_AGENT wasn't found.");
            }
            ticketObj.setQw_agentid(new Long(defaultTicketAgent));
            // set product
            String defaultTicketProduct = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_PRODUCT");
            if(defaultTicketProduct == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_PRODUCT wasn't found.");
            }
            ticketObj.setQw_productid(new Long(defaultTicketProduct));
            // set rvision
            String defaultTicketRVersion = SysPropertyManager.getProperty(
                    "IN_EMAIL_TICKET_RVERSION");
            if(defaultTicketRVersion == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_TICKET_RVERSION wasn't found.");
            }
            ticketObj.setQw_repbuildversionid(new Long(defaultTicketRVersion));

            // check and set problem field
            if(inboxMessage.getSubject().length() > 255) {
                ticketObj.setQw_problem(inboxMessage.getSubject().substring(0,
                        250));
            } else {
                ticketObj.setQw_problem(inboxMessage.getSubject());
            }

            // check and set description field
            if(inboxMessage.getBody() == null) {
                ticketObj.setQw_description(inboxMessage.getSubject());
            } else {
                String body = inboxMessage.getBody();
                if(StringHelper.isHTML(body)) {
                    body = StringHelper.html2text(body);
                }
                if(body.length() > 2000) {
                    ticketObj.setQw_description(body.substring(0, 1900));
                } else {
                    ticketObj.setQw_description(body);
                }
            } // if (message.getBody() == null)

            String messageBody;
            if(inboxMessage.getBody() == null) {
                messageBody = inboxMessage.getSubject();
            } else {
                messageBody = inboxMessage.getBody();
            }

            String descriptionText = getSeparatorStringMemo(inboxMessage) +
                    messageBody;

            // set description
            ticketObj.setQw_descriptiontext(descriptionText.toCharArray());

            // set owner and workgroup
            Long ownerID = inboxMessage.getResipient();
            Long workgroupID = inboxMessage.getWorkgroupId();
            if(ownerID == null && workgroupID == null) {
                // set default owner
                String defaultTicketOwner = SysPropertyManager.getProperty(
                        "IN_EMAIL_TICKET_OWNER");
                if(defaultTicketOwner == null) {
                    throw new NullPointerException(
                            "The system property IN_EMAIL_TICKET_OWNER wasn't found.");
                }
                ticketObj.setQw_ownerid(new Long(defaultTicketOwner));
                inboxMessage.setResipient(new Long(defaultTicketOwner));
                DEBUG(
                        "The inbox message was routed to the system property customer. The ID is "
                                + new Long(defaultTicketOwner));
            } else if(ownerID != null) {
                ticketObj.setQw_ownerid(ownerID);
            } else if(workgroupID != null) {
                ticketObj.setQw_workgroupid(workgroupID);
            } // if (ownerID == null && workgroupID == null)

            // link to the customer
            if(inboxMessage.getSenderType() == CustomInboxHelper
                    .CUSTOMER_TYPE) {
                ticketObj.setQw_customerid(inboxMessage.getSenderID());
            } else if(inboxMessage.getSenderType() == CustomInboxHelper
                    .CUSTOMER_INTERNAL_TYPE) {
                ticketObj.setQw_employeeid(inboxMessage.getSenderID());
            } else {
                throw new NullPointerException(
                        "Unsupported Customer Type. The ticket wasn't created.");
            } // if (inboxMessage.getSenderType() == CustomInboxHelper.CUSTOMER_TYPE)

            hnd.commit();

            // set ticket ID for log
            ticketID = ticketObj.getQw_ticketid();

            inboxMessage.setObjectInfo(ticketObj.getQw_ticketid(),
                    ApplicationHelper.TICKET_OBJECT_TYPE);

            // if the appropriate interaction was created for this ticket
            if(interactionId != null) {
                createLinkInteractionTicket(ls, interactionId,
                        inboxMessage.getObjectId());
            }

        } catch (Exception ex) {
            error = ex;
        } // try

        // Logging.
        try {
            if(error != null) {
                String logMessage = "Can't create a new ticket: " + error
                        .getMessage();
                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.ERROR(logMessage, inboxMessage);
                ERROR(logMessage, error);
                throw error;
            } else {
                String logMessage =
                        "The new ticket was created. The ticket ID is "
                                + ticketID;
                INFO(logMessage + " Time (ms) - "
                        + (System.currentTimeMillis() - time) +
                        ". Message: " + inboxMessage);

                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.INFO(logMessage, inboxMessage);
            } // if (error != null)

        } catch (Exception ex) {
            // Re-throwing the exception.
            throwException("Known exception: " + ex.getMessage(), ex);
        } // try

        INFO("The new ticket was created");
        return true;
    } // createTicket(LogonSession, InboxMessage) : boolean

    /**
     * The method updates a ticket by message.
     *
     * @param ls           logon session object
     * @param inboxMessage message object
     * @return true
     */
    public boolean updateTicket(LogonSession ls, InboxMessage inboxMessage) {

        INFO("Update the existing ticket by the message...");
        long time = System.currentTimeMillis();
        Exception error = null;

        JEOManagerLocal jeoManager = getJEOManager();
        JEObjectHandler ticketHnd;
        // Save!
        try {

            ticketHnd = TicketMailObjectHandler.selectByID(jeoManager, ls,
                    inboxMessage.getObjectId().longValue());
            // If no ticket found.
            if(ticketHnd == null) {
                String errorMessage =
                        "The ticket wasn't found. The ticket ID is "
                                + inboxMessage.getObjectId().longValue();
                ERROR(errorMessage);
                throw new GenericSystemException(errorMessage);
            } else {
                TicketMailObject ticketObject = (TicketMailObject) ticketHnd
                        .getJEObject();

                String descriptionText = "";
                if(ticketObject.getQw_descriptiontext() != null) {
                    descriptionText = new String(
                            ticketObject.getQw_descriptiontext());
                }

                String messageBody;
                if(inboxMessage.getBody() == null) {
                    messageBody = inboxMessage.getSubject();
                } else {
                    messageBody = inboxMessage.getBody();
                }

                String newDescription = getSeparatorStringMemo(inboxMessage) +
                        messageBody +
                        InboxHelper.DELIMITER_HTML +
                        InboxHelper.DELIMITER_HTML +
                        descriptionText;

                ticketObject.setQw_descriptiontext(
                        newDescription.toCharArray());

                ticketHnd.commit();

            } // if (ticketHnd == null)
        } catch (Exception ex) {
            error = ex;
        } // try

        // Logging.
        try {
            if(error != null) {
                String logMessage = "The ticket wasn't updated: " + error
                        .getMessage();
                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.ERROR(logMessage, inboxMessage);
                ERROR(logMessage, error);
                throw error;
            } else {
                String logMessage = "The ticket was updated. The ticket ID is "
                        + inboxMessage.getObjectId().longValue();
                INFO(logMessage + " Time (ms) - "
                        + (System.currentTimeMillis() - time) +
                        ". Message: " + inboxMessage);

                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.INFO(logMessage, inboxMessage);
            } // if (error != null)

        } catch (Exception ex) {
            // Re-throwing the exception.
            throwException("Known exception: " + ex.getMessage(), ex);
        } // try

        INFO("The ticket was updated");

        return true;
    } // createTicket(LogonSession, InboxMessage) : boolean

    /**
     * The method creates a interaction by the message.
     *
     * @param ls           logon session object
     * @param inboxMessage message object
     * @return interactio ID
     */
    public Long createInteraction(LogonSession ls, InboxMessage inboxMessage) {

        INFO("Create a new interaction by the message...");
        long time = System.currentTimeMillis();
        Exception error = null;

        Long interactionId;

        //JEOManagerLocal jeoManager = getJEOManager();
        // Save!
        try {

            // check is the customer has already got
            if(inboxMessage.getSenderID() == null) {
                Long customerID = getCustomer(ls, inboxMessage);
                if(customerID == null) {
                    // try to get the default customer
                    String emailDefaulCustomer = SysPropertyManager.getProperty(
                            "IN_EMAIL_DEFAULT_CUSTOMER_ID");
                    if(emailDefaulCustomer != null) {
                        inboxMessage.setSenderID(new Long(emailDefaulCustomer));
                        inboxMessage.setSenderType(
                                CustomInboxHelper.CUSTOMER_TYPE);
                    } else {
                        // the ticket isn't linked
                        throw new NullPointerException(
                                "The system property IN_EMAIL_DEFAULT_CUSTOMER_ID wasn't found.");
                    } // if (emailDefaulCustomer != null)
                } // if (customerID != null)
            } // if (inboxMessage.getSenderID() == null)

            String emailSourceId = SysPropertyManager.getProperty(
                    "IN_EMAIL_INTER_SOURCE");
            if(emailSourceId == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_INTER_SOURCE wasn't found.");
            }
            String emailDefaulAgentId = SysPropertyManager.getProperty(
                    "IN_EMAIL_INTER_DEFAULT_AGENT");
            if(emailDefaulAgentId == null) {
                throw new NullPointerException(
                        "The system property IN_EMAIL_INTER_DEFAULT_AGENT wasn't found.");
            }
            JEOManagerLocal jeoManager = getJEOManager();
            // try to create ne Interaction object
            JEObjectHandler hnd = jeoManager.create(ls,
                    InteractionObjectHandler.class);
            InteractionObject interactionObj = (InteractionObject) hnd
                    .getJEObject();
            interactionObj.setQw_source(new Integer(emailSourceId));
            // check and set problem field
            if(inboxMessage.getSubject().length() > 255) {
                interactionObj.setQw_problem(
                        inboxMessage.getSubject().substring(0, 250));
            } else {
                interactionObj.setQw_problem(inboxMessage.getSubject());
            }

            // check and set description field
            if(inboxMessage.getBody() == null) {
                interactionObj.setQw_description(inboxMessage.getSubject());
            } else {
                String body = inboxMessage.getBody();
                if(StringHelper.isHTML(body)) {
                    body = StringHelper.html2text(body);
                }
                if(body.length() > 2000) {
                    interactionObj.setQw_description(body.substring(0, 1900));
                } else {
                    interactionObj.setQw_description(body);
                }
            } // if (message.getBody() == null)

            interactionObj.setQw_notes(inboxMessage.getBody().toCharArray());

            interactionObj.setQw_agentid(new Long(emailDefaulAgentId));

            // link to the customer
            if(inboxMessage.getSenderType() == CustomInboxHelper
                    .CUSTOMER_TYPE) {
                interactionObj.setQw_customerid(inboxMessage.getSenderID());
            } else if(inboxMessage.getSenderType() == CustomInboxHelper
                    .CUSTOMER_INTERNAL_TYPE) {
                interactionObj.setQw_employeeid(inboxMessage.getSenderID());
            } else {
                throw new NullPointerException(
                        "Unsupported Customer Type. The interaction wasn't created.");
            } // if (inboxMessage.getSenderType() == CustomInboxHelper.CUSTOMER_TYPE)

            hnd.commit();

            interactionId = interactionObj.getQw_interactionid();
        } catch (Exception ex) {
            error = ex;
            interactionId = null;
        } // try

        // Logging.
        try {
            if(error != null) {
                String logMessage = "Can't create a new interaction: " + error
                        .getMessage();
                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.ERROR(logMessage, inboxMessage);
                ERROR(logMessage, error);
                throw error;
            } else {
                String logMessage =
                        "The new interaction was created. The interaction ID is "
                                + interactionId;
                INFO(logMessage + " Time (ms) - "
                        + (System.currentTimeMillis() - time) +
                        ". Message: " + inboxMessage);

                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.INFO(logMessage, inboxMessage);
            } // if (error != null)

        } catch (Exception ex) {
            // Re-throwing the exception.
            throwException("Known exception: " + ex.getMessage(), ex);
        } // try

        INFO("The new interaction was created");

        return interactionId;
    } // createInteraction(LogonSession, InboxMessage) : Long

    /**
     * The method creates a interaction by the interaction. It is used for reply sending.
     *
     * @param ls           logon session object
     * @param inboxMessage message object
     * @return interactio ID
     */
    public Long createInteractionByInteraction(LogonSession ls,
                                               InboxMessage inboxMessage) {

        INFO("Create a new interaction by the interaction...");
        long time = System.currentTimeMillis();
        Exception error = null;

        Long interactionId;

        JEOManagerLocal jeoManager = getJEOManager();
        // Save!
        try {
            // get existing interaction
            JEObjectHandler interactionHnd = InteractionObjectHandler
                    .selectByID(jeoManager, ls,
                            inboxMessage.getObjectId().longValue());
            // If no ticket found.
            if(interactionHnd == null) {
                String errorMessage =
                        "The interaction wasn't found. The interaction ID is "
                                + inboxMessage.getObjectId().longValue();
                ERROR(errorMessage);
                throw new GenericSystemException(errorMessage);
            }
            InteractionObject interactionObject
                    = (InteractionObject) interactionHnd.getJEObject();

            String emailSourceId = SysPropertyManager.getProperty(
                    "OUT_EMAIL_INTER_SOURCE");
            if(emailSourceId == null) {
                throw new NullPointerException(
                        "The system property OUT_EMAIL_INTER_SOURCE wasn't found.");
            }

            // try to create ne Interaction object
            JEObjectHandler hnd = jeoManager.create(ls,
                    InteractionObjectHandler.class);
            InteractionObject interactionObj = (InteractionObject) hnd
                    .getJEObject();
            interactionObj.setQw_source(new Integer(emailSourceId));
            // check and set problem field
            if(inboxMessage.getSubject().length() > 255) {
                interactionObj.setQw_problem(
                        inboxMessage.getSubject().substring(0, 250));
            } else {
                interactionObj.setQw_problem(inboxMessage.getSubject());
            }

            // check and set description field
            if(inboxMessage.getBody() == null) {
                interactionObj.setQw_description(inboxMessage.getSubject());
            } else {
                String body = inboxMessage.getBody();
                if(StringHelper.isHTML(body)) {
                    body = StringHelper.html2text(body);
                }
                if(body.length() > 2000) {
                    interactionObj.setQw_description(body.substring(0, 1900));
                } else {
                    interactionObj.setQw_description(body);
                }
            } // if (message.getBody() == null)

            interactionObj.setQw_agentid(interactionObject.getQw_agentid());
            interactionObj.setQw_customerid(
                    interactionObject.getQw_customerid());
            interactionObj.setQw_employeeid(
                    interactionObject.getQw_employeeid());
            interactionObj.setQw_notes(inboxMessage.getBody().toCharArray());

            hnd.commit();

            interactionId = interactionObj.getQw_interactionid();
        } catch (Exception ex) {
            error = ex;
            interactionId = null;
        } // try

        // Logging.
        try {
            if(error != null) {
                String logMessage = "Can't create a new interaction: " + error
                        .getMessage();
                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.ERROR(logMessage, inboxMessage);
                ERROR(logMessage, error);
                throw error;
            } else {
                String logMessage =
                        "The new interaction was created. The interaction ID is "
                                + interactionId;
                INFO(logMessage + " Time (ms) - "
                        + (System.currentTimeMillis() - time) +
                        ". Message: " + inboxMessage);

                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.INFO(logMessage, inboxMessage);
            } // if (error != null)

        } catch (Exception ex) {
            // Re-throwing the exception.
            throwException("Known exception: " + ex.getMessage(), ex);
        } // try

        INFO("The new interaction was created");

        return interactionId;
    } // createInteraction(LogonSession, InboxMessage) : Long

    /**
     * The method creates a interaction by the ticket.
     *
     * @param ls           logon session object
     * @param inboxMessage inbox message object
     * @return Long if the interaction was created
     */
    public Long createInteractionByTicket(LogonSession ls,
                                          InboxMessage inboxMessage) {

        INFO("Create a new interaction by the outgoing message...");
        long time = System.currentTimeMillis();
        Exception error = null;

        Long interactionId;

        JEOManagerLocal jeoManager = getJEOManager();
        // Save!
        try {

            // get existing ticket
            JEObjectHandler ticketHnd = TicketMailObjectHandler.selectByID(
                    jeoManager, ls, inboxMessage.getObjectId().longValue());
            // If no ticket found.
            if(ticketHnd == null) {
                String errorMessage =
                        "The ticket wasn't found. The ticket ID is "
                                + inboxMessage.getObjectId().longValue();
                ERROR(errorMessage);
                throw new GenericSystemException(errorMessage);
            }
            TicketMailObject ticketObject = (TicketMailObject) ticketHnd
                    .getJEObject();

            String emailSourceId = SysPropertyManager.getProperty(
                    "OUT_EMAIL_INTER_SOURCE");
            if(emailSourceId == null) {
                throw new NullPointerException(
                        "The system property OUT_EMAIL_INTER_SOURCE wasn't found.");
            }

            // try to create ne Interaction object
            JEObjectHandler hnd = jeoManager.create(ls,
                    InteractionObjectHandler.class);
            InteractionObject interactionObj = (InteractionObject) hnd
                    .getJEObject();
            interactionObj.setQw_source(new Integer(emailSourceId));
            // check and set problem field
            if(inboxMessage.getSubject().length() > 255) {
                interactionObj.setQw_problem(
                        inboxMessage.getSubject().substring(0, 250));
            } else {
                interactionObj.setQw_problem(inboxMessage.getSubject());
            }

            // check and set description field
            if(inboxMessage.getBody() == null) {
                interactionObj.setQw_description(inboxMessage.getSubject());
            } else {
                String body = inboxMessage.getBody();
                DEBUG("1111111111111111111111111111111");
                DEBUG(body);
                DEBUG("1111111111111111111111111111111");
                if(StringHelper.isHTML(body)) {
                    body = StringHelper.html2text(body);
                }
                DEBUG("2222222222222222222222222222222");
                DEBUG(body);
                DEBUG("2222222222222222222222222222222");
                if(body.length() > 2000) {
                    interactionObj.setQw_description(body.substring(0, 1900));
                } else {
                    interactionObj.setQw_description(body);
                }
            } // if (message.getBody() == null)

            interactionObj.setQw_customerid(ticketObject.getQw_customerid());
            interactionObj.setQw_employeeid(ticketObject.getQw_employeeid());
            interactionObj.setQw_agentid(ticketObject.getQw_agentid());

            hnd.commit();

            interactionId = interactionObj.getQw_interactionid();
        } catch (Exception ex) {
            error = ex;
            interactionId = null;
        } // try

        // Logging.
        try {
            if(error != null) {
                String logMessage = "Can't create a new interaction: " + error
                        .getMessage();
                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.ERROR(logMessage, inboxMessage);
                ERROR(logMessage, error);
                throw error;
            } else {
                String logMessage =
                        "The new interaction was created. The interaction ID is "
                                + interactionId;
                INFO(logMessage + " Time (ms) - "
                        + (System.currentTimeMillis() - time) +
                        ". Message: " + inboxMessage);

                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.INFO(logMessage, inboxMessage);
            } // if (error != null)

        } catch (Exception ex) {
            // Re-throwing the exception.
            throwException("Known exception: " + ex.getMessage(), ex);
        } // try

        INFO("The new interaction was created");

        return interactionId;
    } // createInteractionByTicket(LogonSession, InboxMessage) : Long

    public boolean createLinkInteractionTicket(LogonSession ls,
                                               Long interactionID,
                                               Long ticketID)
            throws EQLException {

        DEBUG("Try to create a link between the Interaction #" + interactionID +
                " and the Ticket #" + ticketID
        );

        JEOManagerLocal jeoManager = getJEOManager();
        JEObjectHandler hnd = jeoManager.create(ls,
                InteractionTicketObjectHandler.class);
        InteractionTicketObject linkObj = (InteractionTicketObject) hnd
                .getJEObject();
        linkObj.setQw_interactionid(interactionID);
        linkObj.setQw_ticketid(ticketID);
        hnd.commit();
        DEBUG("The link between the Interaction #" + interactionID +
                " and the Ticket #" + ticketID + " was created."
        );
        return true;
    } // createLinkInteractionTicket(LogonSession, Long, Long) : boolean

    /**
     * The method sends a reply by the ticket. It updates ticket information and creates a new Interaction.
     *
     * @param ls           logon session object
     * @param inboxMessage inbox message object
     * @param mailHeaders  mail headers
     * @return true the reply was sent
     * @throws Exception the reply wasn't sent
     */
    public boolean sendReply(LogonSession ls, InboxMessage inboxMessage,
                             Properties mailHeaders) throws Exception {

        INFO("Send reply by object...");

        Long interactionID;
        boolean returnValue = false;
        // update email body
        if(!setImageAttachmentLoader(ls, inboxMessage)) {
            throw new GenericSystemException(
                    "Can't update an email body. The email body is not valid.");
        } else {
            if(inboxMessage.getObjectType().compareTo(
                    ApplicationHelper.INTERACTION_OBJECT_TYPE) == 0) {
                interactionID = createInteraction(ls, inboxMessage);
                if(interactionID != null) {
                    returnValue = true;
                }
            } else if(inboxMessage.getObjectType().compareTo(
                    ApplicationHelper.TICKET_OBJECT_TYPE) == 0) {
                interactionID = createInteractionByTicket(ls, inboxMessage);
                if(interactionID != null) {
                    returnValue = createLinkInteractionTicket(ls, interactionID,
                            inboxMessage.getObjectId());
                    if(returnValue) {
                        returnValue = updateTicket(ls, inboxMessage);
                    }
                } else {
                    // empty
                    returnValue = false;
                } // if (interactionID != null)
                // save new attachements for this ticket
                if(inboxMessage.getProcessId() != null) {
                    // get temp attachments
                    AttachmentTempObject[] dbAttachments;
                    dbAttachments = getAttachments(
                            inboxMessage.getProcessId().longValue(), ls);
                    if(dbAttachments.length > 0) {
                        // save attachements
                        linkAttachmentsToObject(ls, inboxMessage);
                    }
                } // if (inboxMessage.getProcessId() != null)
            } else {
                throw new GenericSystemException("Unsupported object type");
            } // if (inboxMessage.getObjectType() == ApplicationHelper.INTERACTION_OBJECT_TYPE)
        }

        if(returnValue) {
            returnValue = super.sendEmailMessage(ls, inboxMessage, mailHeaders);
            setReplyDateToInbox(ls, inboxMessage);
        } // if (! setImageAttachmentLoader(ls, inboxMessage))

        if(returnValue) {
            INFO("The the reply was sent");
        } else {
            INFO("The the reply wasn't sent");
        }

        return returnValue;
    } // sendReply(LogonSession, InboxMessage, Properties) : boolean

    // ------------------------------------------------------- Private methods


    /**
     * The method returns a separator string for memo fields.
     *
     * @param inboxMessage inbox message object
     * @return separator string
     */
    protected String getSeparatorStringMemo(InboxMessage inboxMessage) {
        return CustomInboxHelper.INDICATION_PREFIX_HTML +
                inboxMessage.getFrom().getEmail() +
                CustomInboxHelper.getDateAsString() +
                CustomInboxHelper.INDICATION_POSTFIX_HTML +
                CustomInboxHelper.DELIMITER_HTML
                ;
    } // getSeparatorStringMemo(InboxMessage) : String

    /**
     * The method gets the customer by
     *
     * @param ls           logon session object
     * @param inboxMessage inbox message object
     * @return customer ID
     */
    private Long getCustomer(LogonSession ls, InboxMessage inboxMessage) {

        INFO("Get the Customer to the object...");
        long time = System.currentTimeMillis();
        Exception error = null;


        Long customerID = null;
        try {
            customerID = findCustomer(ls, inboxMessage.getFrom().getEmail());
            // If customer wasn't found.
            if(customerID == null) {
                INFO("Try to find internal customer...");
                customerID = findInternalCustomer(ls,
                        inboxMessage.getFrom().getEmail());
                if(customerID == null) {
                    INFO("The customer wasn't found. Create new Customer...");
                    JEOManagerLocal jeoManager = getJEOManager();
                    JEObjectHandler hnd = jeoManager.create(ls,
                            CustomerObjectHandler.class);
                    CustomerObject customerObj = (CustomerObject) hnd
                            .getJEObject();
                    String fullName = inboxMessage.getFrom().getFullName();
                    if(fullName != null) {
                        customerObj.setQw_fullname(fullName);
                    } else {
                        // try get default customer name
                        String defaultCustomerName = SysPropertyManager
                                .getProperty("IN_EMAIL_DEFAULT_CUSTOMER_NAME");
                        if(defaultCustomerName != null) {
                            customerObj.setQw_fullname(defaultCustomerName);
                        } else {
                            // leave the fullname field empty
                        } // if (defaultCustomerName != null)
                    } // if (fullName != null)
                    customerObj.setQw_email(inboxMessage.getFrom().getEmail());
                    hnd.commit();
                    customerID = customerObj.getQw_customerid();
                    inboxMessage.setSenderID(customerID);
                    inboxMessage.setSenderType(CustomInboxHelper.CUSTOMER_TYPE);
                    INFO("The new customer was created.");
                } else {
                    inboxMessage.setSenderID(customerID);
                    inboxMessage.setSenderType(
                            CustomInboxHelper.CUSTOMER_INTERNAL_TYPE);
                } // if (customerID == null)
            } else {
                inboxMessage.setSenderID(customerID);
                inboxMessage.setSenderType(CustomInboxHelper.CUSTOMER_TYPE);
            } // if (customerID == null)

        } catch (Exception ex) {
            error = ex;
        } // try

        // Logging.
        try {
            if(error != null) {
                String logMessage =
                        "Can't get the customer to link to the object: " + error
                                .getMessage();
                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.ERROR(logMessage, inboxMessage);
                ERROR(logMessage, error);
                customerID = null;
            } else {
                String logMessage =
                        "The customer was found. The customer's ID is "
                                + customerID;
                INFO(logMessage + " Time (ms) - "
                        + (System.currentTimeMillis() - time) +
                        ". EmailAddress: " + inboxMessage.getFrom().getEmail());

                InboxLogPublisher publisher = new InboxLogPublisher(ls);
                publisher.INFO(logMessage, inboxMessage);
            } // if (error != null)

        } catch (Exception ex) {
            // Re-throwing the exception.
            throwException("Known exception: " + ex.getMessage(), ex);
        } // try

        return customerID;
    } // getCustomer(LogonSession, InboxMessage) : Long

    /**
     * The method searches a customer by specified parameters.
     *
     * @param ls           logon session object
     * @param emailAddress email address
     * @return customer ID
     * @throws EQLException EQLManager return an exception
     */
    private Long findCustomer(LogonSession ls, String emailAddress)
            throws EQLException {

        Long customerID;
        if(emailAddress != null) {
            DEBUG("Try to find the customer by email - " + emailAddress);
            EQLManagerLocal eqlManager = getEQLManagerLocal();
            customerID = CustomerObjectHandler.selectIDByEmail(eqlManager, ls,
                    emailAddress);
        } else {
            customerID = null;
        } // if

        return customerID;
        //return new Long(-1000);
    } // findCustomer(LogonSession, String) : Long

    /**
     * The method searches a internal customer by specified parameters.
     *
     * @param ls           logon session object
     * @param emailAddress email address
     * @return customer ID
     * @throws EQLException EQLManager return an exception
     */
    private Long findInternalCustomer(LogonSession ls, String emailAddress)
            throws EQLException {

        Long customerID;
        if(emailAddress != null) {
            DEBUG("Try to find the internal customer by email - "
                    + emailAddress);
            EQLManagerLocal eqlManager = getEQLManagerLocal();
            customerID = EmployeeObjectHandler.selectIDByEmail(eqlManager, ls,
                    emailAddress);
        } else {
            customerID = null;
        } // if

        return customerID;
    } // findInternalCustomer(LogonSession, String) : Long

    // ------------------------------------------------------- Protected methods

    protected static EQLManagerLocal getEQLManagerLocal() {
        CacheObjectManager com = new CacheObjectManager();
        return (EQLManagerLocal) com.getLocalObject(JNDINames.EQLManager,
                EQLManagerLocalHome.class);
    }

    // Gets an array of temporary attachment value objects.
    private AttachmentTempObject[] getAttachments(long process_id,
                                                  LogonSession ls) {
        return getAttachmentManager().getTempAttachments(ls, process_id);
    }

    // Gets Attachment Manager EJB reference.
    private AttachmentManagerLocal getAttachmentManager() {
        return (AttachmentManagerLocal) getLocalObject(
                JNDINames.AttachmentManager, AttachmentManagerLocalHome.class);
    }
} // class InboxManagerEJB
