/*
 * 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.notification;

import com.queplix.core.error.ErrorHelper;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.integrator.security.User;
import com.queplix.core.integrator.security.WorkGroup;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.jeo.JEObject;
import com.queplix.qwoss.gen.NotifPriorityFieldObject;
import com.queplix.qwoss.gen.NotifPriorityFieldObjectHandler;
import com.queplix.qwoss.gen.NotifRecipientFieldObject;
import com.queplix.qwoss.gen.NotifRecipientFieldObjectHandler;
import com.queplix.qwoss.gen.NotifStatusFieldObject;
import com.queplix.qwoss.gen.NotifStatusFieldObjectHandler;
import com.queplix.qwoss.gen.TicketNotificationObject;
import com.queplix.qwoss.gen.TicketNotificationObjectHandler;
import com.queplix.qwoss.gen.TicketObject;
import com.queplix.qwoss.gen.TicketObjectHandler;
import com.queplix.qwoss.utils.ApplicationHelper;
import com.queplix.qwoss.utils.TicketNotificationHelper;
import java.util.List;

/**
 * <p/>
 * Ticket notification manager EJB
 * </p>
 *
 * @author [ALB] Baranov Andrey
 * @version $Revision: 1.8.2.2 $ $Date: 2005/12/20 16:43:05 $
 */

public class TicketNotificationManagerEJB
        extends
        AbstractEntityNotificationManagerEJB {

    // currently updated JEObject (Ticket) 
    protected JEObject jeObject;
    
    // special ticket attributes
    private Long pkey;
    private Integer status;
    private Integer priority;
    private User agent;
    private User owner;
    private User intCustomer;
    private String customerMail;
    private WorkGroup group;

    /**
     * Initialize bean
     *
     * @param ls         LogonSession object
     * @param ticketObject case JEO
     */
    public void ejbCreate(LogonSession ls, TicketObject ticketObject) {
        INFO("TicketNotificationManagerEJB create - " + hashCode());
        // checking
        if(ticketObject == null) {
            throw new IllegalStateException("Ticket object is NULL");
        }
        // initialization
        init(ls, TicketObjectHandler.ENTITY, ticketObject.getQw_ticketid(),
                ApplicationHelper.TICKET_OBJECT_TYPE);
        this.jeObject = ticketObject;
    }

    /**
     * Initialize bean
     *
     * @param ls       LogonSession object
     * @param ticketId ticket id
     */
    public void ejbCreate(LogonSession ls, Long ticketId) {
        INFO("TicketNotificationManagerEJB create - " + hashCode());
        // checking
        if(ticketId == null) {
            throw new IllegalStateException("Ticket ID is NULL");
        }
        // initialization
        init(ls, TicketObjectHandler.ENTITY, ticketId,
                ApplicationHelper.TICKET_OBJECT_TYPE);
        TicketObjectHandler hnd = null;
        try {
            hnd = (TicketObjectHandler) TicketObjectHandler.selectByID(jeoManager, ls, ticketId);
        } catch (EQLException ex) {
            throwException(ex);
        }
        if(hnd == null) {
            throwException("Case #" + ticketId + " not found!");
        }
        this.jeObject = hnd.getJEObject();
    }

    // ----------------------------------------------------- busines methods

    /**
     * Send ticket notification
     */
    public void doNotification() {

        long time = System.currentTimeMillis();
        // Initialization
        NotificationManagerLocal notificationLocal = getNotificationManagerLocal();
        // Go!
        try {
            //
            // 1. Find ticket notifications by the ticket parameters
            //
            List notificationObjectList = getNotificationObjectList();
            if(notificationObjectList != null) {
                //
                // 2. For each notification do the following...
                //
                int size = notificationObjectList.size();
                for(int i = 0; i < size; i++) {
                    TicketNotificationObjectHandler hnd = 
                        (TicketNotificationObjectHandler) notificationObjectList.get(i);
                    TicketNotificationObject notification = (TicketNotificationObject) hnd.getJEObject();
                    // Do not send notification, if disabled
                    if(notification.getQw_disable() == 1) {
                        INFO("Skip notification process. Ticket action is disabled.");
                        continue;
                    }
                    Long notificationID = notification.getQw_notificationid();
                    // Check for equal status
                    List<NotifStatusFieldObjectHandler> notificationStatusHandlers
                        = NotifStatusFieldObjectHandler.selectByNotificationId(jeoManager, ls, notificationID);
                    if(notificationStatusHandlers != null) {
                        boolean returned = false;
                        for(NotifStatusFieldObjectHandler notifStatusFieldObjectHandler : notificationStatusHandlers) {
                            NotifStatusFieldObject notifStatusFieldObject = 
                                (NotifStatusFieldObject) notifStatusFieldObjectHandler.getJEObject();
                            if((getObjectStatus() != null) && 
                               (notifStatusFieldObject.getQw_status().intValue() == getObjectStatus())) {
                                returned = true;
                                break;
                            }
                        }
                        if(!returned) {
                            continue;
                        }
                    }
                    // Check for equal priority
                    List<NotifPriorityFieldObjectHandler> notificationPriorityHandlers
                        = NotifPriorityFieldObjectHandler.selectByNotificationId(jeoManager, ls, notificationID);
                    if(notificationPriorityHandlers != null) {
                        boolean returned = false;
                        for(NotifPriorityFieldObjectHandler notifPriorityFieldObjectHandler : notificationPriorityHandlers) {
                            NotifPriorityFieldObject notifPriorityFieldObject =
                                    (NotifPriorityFieldObject) notifPriorityFieldObjectHandler.getJEObject();
                            if((getObjectPriority() != null) &&
                               (notifPriorityFieldObject.getQw_priority().intValue() == getObjectPriority())) {
                                returned = true;
                                break;
                            }
                        }
                        if(!returned) {
                            continue;
                        }
                    }
                    //
                    // 3. Get notification recipients
                    //
                    List<NotifRecipientFieldObjectHandler> notifRecipientHandlers
                        = NotifRecipientFieldObjectHandler.selectByNotificationId(jeoManager, ls, notificationID);
                    notificationLocal.setSubject(notification.getQw_subject());
                    notificationLocal.setMessage( (notification.getQw_mailbody() == null) ? 
                            null : new String( notification.getQw_mailbody()));
                    // All recipients are in
                    if(notifRecipientHandlers != null) {
                        // for all recipients do --
                        for(NotifRecipientFieldObjectHandler notifRecipientFieldObjectHandler : notifRecipientHandlers) {
                            NotifRecipientFieldObject notifRecipientFieldObject
                                    = (NotifRecipientFieldObject) notifRecipientFieldObjectHandler.getJEObject();
                            Integer notifRecipient = notifRecipientFieldObject.getQw_recipient();
                            if(notifRecipient == null) {
                                continue;
                            }
                            User notificationUser = null;
                            WorkGroup notificationGroup = null;
                            String notificationAddr = null;
                            Object notifierObj = determineNotifier(notifRecipient, notification);
                            if(notifierObj instanceof User)
                                notificationUser = (User) notifierObj;
                            else if (notifierObj instanceof WorkGroup)
                                notificationGroup = (WorkGroup) notifierObj;
                            else if (notifierObj instanceof String)
                                notificationAddr = (String) notifierObj;
                            INFO("Notification action #" + i
                                    + "\n   recipient type: " + notifRecipient
                                    + "\n   method: "
                                    + notification.getQw_sendmode()
                                    + "\n   notification user: "
                                    + notificationUser
                                    + "\n   notification group: "
                                    + notificationGroup
                                    + "\n   notification addr: "
                                    + notificationAddr);
                            //
                            // 4. Get notification (action) method. Do this action.
                            //
                            if(notificationAddr != null) {
                                //
                                // 5.1 always send email to addressee
                                //
                                notificationLocal.notifyByMail(notificationAddr);
                            } else if(notification.getQw_sendmode() == null) {
                                //
                                // 5.2 send default notification
                                //
                                if(notificationUser != null) {
                                    // send to user
                                    notificationLocal.notify(notificationUser);
                                } else if(notificationGroup != null) {
                                    // send to group
                                    notificationLocal.notify(notificationGroup, null, null);
                                } else {
                                    // warning!
                                    WARN("Can't send default notification. Recipient is empty.");
                                }
                            } else if(notification.getQw_sendmode() == TicketNotificationHelper.ALERT_METHOD) {
                                //
                                // 5.3 send notification alert
                                //
                                if(notificationUser != null) {
                                    // send alert to user
                                    notificationLocal.notifyByAlert(notificationUser);
                                } else if(notificationGroup != null) {
                                    // send alert to group
                                    notificationLocal.notifyByAlert(notificationGroup, null);
                                } else {
                                    // warning!
                                    WARN("Can't send notification alert. Recipient is empty.");
                                }
                            } else {
                                //
                                // 5.4 send notification mail
                                //
                                if(notificationUser != null) {
                                    // send mail to user
                                    notificationLocal.notifyByMail(notificationUser);
                                } else if(notificationGroup != null) {
                                    // send mail to group
                                    notificationLocal.notifyByMail(notificationGroup);
                                } else {
                                    // warning!
                                    WARN("Can't send notification mail. Recipient is empty.");
                                }
                            }
                        } // --- for all recipients
                    } else {
                        WARN("Can't send notification mail. Recipient is empty.");
                    }
                }
            }
        } catch (EQLException ex) {
            throwException(ex);
        } catch (Throwable t) {
            ErrorHelper.throwSystemException(t, this);
        } finally {
            // remove NotificationManager stateful EJB
            try {
                notificationLocal.remove();
            } catch (Throwable t) {
                ERROR(t);
            }
        }
        // Ok.
        INFO("Ticket notification done (pkey = "+getObjectPkey()+")."+"\nTime (ms) - "+
                (System.currentTimeMillis() - time));
    }

    protected Long getObjectPkey(){
        if(pkey == null)
            pkey = ((TicketObject)jeObject).getQw_ticketid();
        return pkey;
    }
    protected Integer getObjectStatus(){
        if(status == null)
            status = ((TicketObject)jeObject).getQw_status();
        return status;
    }
    protected Integer getObjectPriority(){
        if(priority == null)
            priority = ((TicketObject)jeObject).getQw_priority();
        return priority;
    }
    
    /**
     * Determine the list of suitable notification rules
     */
    protected List getNotificationObjectList(){
        boolean isIntCustomer = false;
        TicketObject  objTicket = (TicketObject)jeObject;
        Long ticketCustomerId = objTicket.getQw_customerid();
        if(ticketCustomerId == null) {
            ticketCustomerId = objTicket.getQw_employeeid();
            isIntCustomer = true;
        }
        INFO("Try to do ticket notification:" +
                "\n   Pkey: " + objTicket.getQw_ticketid() +
                "\n   Priority: " + objTicket.getQw_priority() +
                "\n   Status: " + objTicket.getQw_status() +
                "\n   Product: " + objTicket.getQw_productid() +
                "\n   Ticket Customer: " + ticketCustomerId +
                "\n   Owner: " + objTicket.getQw_ownerid() +
                "\n   Agent: " + objTicket.getQw_agentid());
        try {
            return TicketNotificationObjectHandler.selectByTicketData(jeoManager, ls, 
                    objTicket.getQw_productid(), ticketCustomerId, isIntCustomer);
        } catch (EQLException e) {
            return null;        
        }        
    }

    /**
     * Determine the type of notification recipient (User, Group, or direct email string)
     */
    protected Object determineNotifier(Integer notifRecipient, 
            TicketNotificationObject objNotification){
        Object obj = null;
        TicketObject  objTicket = (TicketObject)jeObject;
        // choose notifier
        if(notifRecipient == TicketNotificationHelper.CUSTOMER_RECIPIENT) {
            // to case customer..
            boolean isIntCustomer = false;
            Long ticketCustomerId = objTicket.getQw_customerid();
            if(ticketCustomerId == null) {
                ticketCustomerId = objTicket.getQw_employeeid();
                isIntCustomer = true;
            }
            if(isIntCustomer) {
                return loadTicketIntCustomer(ticketCustomerId);
            } else {
                return loadTicketCustomer(ticketCustomerId);
            }
        } else if(notifRecipient == TicketNotificationHelper.AGENT_RECIPIENT) {
            // to ticket agent..
            return loadTicketAgent(objTicket.getQw_agentid());
        } else if(notifRecipient == TicketNotificationHelper.OWNER_RECIPIENT) {
            // to ticket owner..
            return loadTicketOwner(objTicket.getQw_ownerid());
        } else if(notifRecipient == TicketNotificationHelper.WORKGROUP_RECIPIENT) {
            // to ticket workgroup..
            return loadTicketGroup(objTicket.getQw_workgroupid());
        } else if(notifRecipient == TicketNotificationHelper.EMAIL_TO_RECIPIENT) {
            // send special email..
            return objNotification.getQw_email();
        }
        return obj;
    }
    
    //
    // Load ticket agent
    //
    protected User loadTicketAgent(Long agentId) {
        if(agent == null) {
            INFO("Trying to load ticket agent #" + agentId);
            agent = loadNotifiedUser(agentId);
        }
        return agent;
    }
    //
    // Load ticket owner
    //
    protected User loadTicketOwner(Long ownerId) {
        if(owner == null) {
            INFO("Trying to load ticket owner #" + ownerId);
            owner = loadNotifiedUser(ownerId);
        }
        return owner;
    }
    //
    // Load ticket group
    //
    protected WorkGroup loadTicketGroup(Long wgroupId) {
        if(group == null) {
            INFO("Trying to load ticket group #" + wgroupId);
            group = loadNotifiedGroup(wgroupId);
        }
        return group;
    }
    //
    // Load ticket Int Customer
    //
    protected User loadTicketIntCustomer(Long intCustomerId) {
        if(intCustomer == null) {
            INFO("Trying to load ticket internal customer #" + intCustomerId);
            try {
                intCustomer = ApplicationHelper.loadEmployee(ls, intCustomerId);
            } catch (EQLException e) {
                throwException(e);
            }
        }
        return intCustomer;
    }
    //
    // Load ticket Customer
    //
    protected String loadTicketCustomer(Long customerId) {
        if(customerMail == null) {
            INFO("Trying to load mail address for ticket customer #" + customerId);
            try {
                customerMail = ApplicationHelper.loadCustomerMail(ls, customerId);
            } catch (EQLException e) {
                throwException(e);
            }
        }
        return customerMail;
    }

}
