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


//import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.integrator.security.User;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.eql.update.EntityUpdate;
import com.queplix.core.modules.jeo.JEObjectHandler;
import com.queplix.core.modules.jeo.ejb.JEOManagerLocal;
import com.queplix.core.modules.jeo.ejb.JEOManagerLocalHome;
import com.queplix.core.utils.DateHelper;
import com.queplix.core.utils.JNDINames;
import com.queplix.qwoss.gen.TicketEventObject;
import com.queplix.qwoss.gen.TicketObject;
import com.queplix.qwoss.gen.TicketObjectHandler;
//import com.queplix.qwoss.notification.TicketEscalationManagerLocal;
//import com.queplix.qwoss.notification.TicketEscalationManagerLocalHome;
//import com.queplix.qwoss.notification.TicketNotificationManagerLocal;
//import com.queplix.qwoss.notification.TicketNotificationManagerLocalHome;
//import com.queplix.qwoss.utils.CustomJNDINames;
import com.queplix.qwoss.utils.TicketEventHelper;
import com.queplix.qwoss.utils.TicketHelper;

//import javax.ejb.CreateException;
import java.util.Date;

/**
 * Description.
 *
 * @author rustem.nizamiev
 * @since 18 January 2007, 15:16
 */
public class TicketUpdate extends EntityUpdate {

    public int beforeUpdate()
            throws EQLException {

        long time = System.currentTimeMillis();

        // Initialization.
        JEOManagerLocal jeoManager = (JEOManagerLocal)
                getCOM().getLocalObject(JNDINames.JEOManager,
                        JEOManagerLocalHome.class);
        LogonSession ls = getEUO().getSession().getLogonSession();
        User user = ls.getUser();
        //Object empObj = ls.getParameter(ApplicationHelper.EMPLOYEE_KEY);
        //if(empObj == null || !(empObj instanceof EmployeeObject))
        //    throw new EQLException("Can't retrieve Employee Id.\nInvalid parameter for key: "+ApplicationHelper.EMPLOYEE_KEY);
        //Long employeeID = ((EmployeeObject) empObj).getQw_employeeid();

        // Get current ticket record.
        JEObjectHandler hnd = getJEOHandler(jeoManager,
                TicketObjectHandler.class);
        TicketObject obj = (TicketObject) hnd.getJEObject();

        // Get ticket ID.
        long ticketID = obj.getQw_ticketid();

        // Now date.
        Date now = DateHelper.getNowDate();

        /**
         * CheckCallLinks function implementation
         */

        // We need to make sure we have a product.
        if(obj.isNullQw_productid()) {
            throw new EQLException(
                    "You must first select a product for this ticket.");
        }
        // We need to make sure we have a status.
        if(obj.isNullQw_status()) {
            throw new EQLException(
                    "You must first select a status for this ticket.");
        }

        // We need to make sure we have customer or employee.
        if(obj.isNullQw_customerid() && obj.isNullQw_employeeid()) {
            throw new EQLException(
                    "You must first select customer or internal customer for this ticket.");
        }
        // We need to make sure we have customer or employee.
        if(!obj.isNullQw_customerid() && !obj.isNullQw_employeeid()) {
            throw new EQLException(
                    "You must specify either customer or internal customer for this ticket.");
        }

        // Now deal with the status fields.  Different things can happen for a status.
        int ticketStatus = obj.getQw_status().intValue();


        if(isNew()) {
            // Only 'New' status is allowed for the first ticket creation 
            if(ticketStatus != TicketHelper.NEW_STATUS) {
                throw new EQLException(
                        "The status for new ticket can be new only.");
            }
        } else {
            // We need to make sure we have a old status.
            int oldStatus = 0;
            try {
                oldStatus = obj.oldQw_status().intValue();
            }
            catch (NullPointerException ex) {
                throw new EQLException(
                        "This ticket was created without status.");
            }

            // Try to set the status automatically if foreign fields require.
            if(ticketStatus != TicketHelper.DUPLICATE_STATUS
                    && oldStatus != TicketHelper.CLOSED_STATUS) {

                // Check to be sure that there is an agent.  If not, supply one
                if(obj.isNullQw_agentid()) {
                    //obj.setQw_agentid( employeeID );
                    obj.setQw_agentid(new Long(user.getUserID()));
                }


                if(!obj.isNullQw_ownerid()) { // there is owner
                    if(ticketStatus == TicketHelper.NEW_STATUS
                            || ticketStatus == TicketHelper.ASSIGNED_STATUS) {
                        long owner = obj.getQw_ownerid().longValue();
                        if(owner == user.getUserID()) {
                            ticketStatus = TicketHelper.OWNED_STATUS;
                            obj.setQw_status(new Integer(ticketStatus));
                        } else {
                            if(ticketStatus == TicketHelper.NEW_STATUS) {
                                ticketStatus = TicketHelper.ASSIGNED_STATUS;
                                obj.setQw_status(new Integer(ticketStatus));
                            }
                            //else{
                            //    throw new EQLException( "Only owner can trigger ticket to owned status." );
                            //}
                        }
                    }
                    if(ticketStatus == TicketHelper.OWNED_STATUS && obj
                            .isChangedQw_ownerid()) {
                        long owner = obj.getQw_ownerid().longValue();
                        if(owner != user.getUserID()) {
                            if(oldStatus != TicketHelper.ASSIGNED_STATUS) {
                                ticketStatus = TicketHelper.ASSIGNED_STATUS;
                                obj.setQw_status(new Integer(ticketStatus));
                                obj.setQw_dateowned(null);
                            }
                        }
                    }
                } else {
                    if(ticketStatus == TicketHelper.OWNED_STATUS) {
                        if(!obj.isNullQw_workgroupid()) {
                            if(oldStatus != TicketHelper.ASSIGNED_STATUS) {
                                ticketStatus = TicketHelper.ASSIGNED_STATUS;
                                obj.setQw_status(new Integer(ticketStatus));
                                obj.setQw_dateowned(null);
                            }
                        } else {
                            throw new EQLException(
                                    "Cannot save ticket in this status without owner or workgroup.");
                        }
                    }
                }

                if(!obj.isNullQw_workgroupid()) { // there is workgroup
                    if(ticketStatus == TicketHelper.NEW_STATUS) {
                        ticketStatus = TicketHelper.ASSIGNED_STATUS;
                        obj.setQw_status(new Integer(ticketStatus));
                        //if( obj.isNullDateassigned() ) {
                        //    obj.setDateassigned( now );
                        //}
                    }
                } else {
                    if(ticketStatus == TicketHelper.ASSIGNED_STATUS && obj
                            .isNullQw_ownerid()) {
                        throw new EQLException(
                                "Cannot save ticket in this status without workgroup.");
                    }
                }
            }

            if(ticketStatus != TicketHelper.CLOSED_STATUS && !obj
                    .isNullQw_reasoncode()) {
                obj.setQw_reasoncode(null);
            }

            INFO("New status: " + ticketStatus + ". Ticket ID: " + ticketID);

            if(obj.isChangedQw_status()) {
                //for the first update we can change status only to 'Owned''
                if(oldStatus == TicketHelper.NEW_STATUS && !(
                        ticketStatus == TicketHelper.ASSIGNED_STATUS ||
                                ticketStatus == TicketHelper.OWNED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from new to assigned or owned only.");
                }
                if(oldStatus == TicketHelper.ASSIGNED_STATUS
                        && ticketStatus != TicketHelper.OWNED_STATUS) {
                    throw new EQLException(
                            "The status can be switched from assigned to owned only.");
                }
                if(oldStatus == TicketHelper.OWNED_STATUS && !(
                        ticketStatus == TicketHelper.ASSIGNED_STATUS ||
                                ticketStatus == TicketHelper
                                        .RELEASE_CANDIDATE_STATUS ||
                                ticketStatus == TicketHelper
                                        .UNREPRODUCIBLE_STATUS ||
                                ticketStatus == TicketHelper.CLIENT_ISSUE_STATUS
                                ||
                                ticketStatus == TicketHelper.DUPLICATE_STATUS ||
                                ticketStatus == TicketHelper.PARKED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from owned to assigned, release candidate, un-reproducible, client issue, duplicate or parked only.");
                }
                if(oldStatus == TicketHelper.RELEASE_CANDIDATE_STATUS
                        && ticketStatus != TicketHelper.DELIVERED_STATUS) {
                    throw new EQLException(
                            "The status can be switched from release candidate to delivered only.");
                }
                if(oldStatus == TicketHelper.DELIVERED_STATUS && !(
                        ticketStatus == TicketHelper.TESTFAIL_STATUS ||
                                ticketStatus == TicketHelper.CLOSED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from the delivered to test fail or closed only.");
                }
                if(oldStatus == TicketHelper.UNREPRODUCIBLE_STATUS && !(
                        ticketStatus == TicketHelper.OWNED_STATUS ||
                                ticketStatus == TicketHelper.CLIENT_ISSUE_STATUS
                                ||
                                ticketStatus == TicketHelper.DUPLICATE_STATUS ||
                                ticketStatus == TicketHelper.PARKED_STATUS ||
                                ticketStatus == TicketHelper.CLOSED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from un-reproducible to owned, client issue, duplicate, parked or closed only.");
                }
                if(oldStatus == TicketHelper.CLIENT_ISSUE_STATUS
                        && ticketStatus != TicketHelper.CLOSED_STATUS) {
                    throw new EQLException(
                            "The status can be switched from client issue to closed only.");
                }
                if(oldStatus == TicketHelper.DUPLICATE_STATUS && !(
                        ticketStatus == TicketHelper.OWNED_STATUS ||
                                ticketStatus == TicketHelper
                                        .UNREPRODUCIBLE_STATUS ||
                                ticketStatus == TicketHelper.CLIENT_ISSUE_STATUS
                                ||
                                ticketStatus == TicketHelper.PARKED_STATUS ||
                                ticketStatus == TicketHelper.CLOSED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from duplicate to owned, un-reproducible, client issue, parked or closed only.");
                }
                if(oldStatus == TicketHelper.PARKED_STATUS && !(
                        ticketStatus == TicketHelper.OWNED_STATUS ||
                                ticketStatus == TicketHelper
                                        .UNREPRODUCIBLE_STATUS ||
                                ticketStatus == TicketHelper.CLIENT_ISSUE_STATUS
                                ||
                                ticketStatus == TicketHelper.DUPLICATE_STATUS ||
                                ticketStatus == TicketHelper.CLOSED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from parked to owned, un-reproducible, client issue, duplicate or closed only.");
                }
                if(oldStatus == TicketHelper.TESTFAIL_STATUS && !(
                        ticketStatus == TicketHelper.OWNED_STATUS ||
                                ticketStatus == TicketHelper.ASSIGNED_STATUS)) {
                    throw new EQLException(
                            "The status can be switched from test fail to owned only.");
                }
                // The ticket is going to be re-open 
                if(oldStatus == TicketHelper.CLOSED_STATUS) {
                    if(!(ticketStatus == TicketHelper.NEW_STATUS
                            || ticketStatus == TicketHelper.ASSIGNED_STATUS
                            || ticketStatus == TicketHelper.OWNED_STATUS)
                            ) {
                        throw new EQLException(
                                "The status for re-opened tickets must be new,assigned or owned only.");
                    }
                    // Set Last reopen date and increment re-open counter
                    obj.setQw_lastreopened(now);
                    int reopencnt = 0;
                    if(obj.getQw_reopencnt() != null) {
                        reopencnt = obj.getQw_reopencnt().intValue();
                    }
                    reopencnt++;
                    obj.setQw_reopencnt(new Integer(reopencnt));
                    //obj.setQw_dateassigned( null );
                    //obj.setQw_dateowned( null );
                    obj.setQw_datedelivered(null);
                    obj.setQw_dateclosed(null);
                    obj.setQw_reasoncode(null);
                    obj.setQw_otherreason(null);
                    obj.setQw_resbuildversionid(null);
                }

                switch(ticketStatus) {

                    case TicketHelper.ASSIGNED_STATUS:
                        if(obj.isNullQw_workgroupid() && obj
                                .isNullQw_ownerid()) {
                            throw new EQLException(
                                    "Cannot save ticket in this status without owner or workgroup.");
                        }
                        obj.setQw_dateassigned(now);
                        obj.setQw_datedelivered(null);
                        obj.setQw_resbuildversionid(null);
                        break;

                    case TicketHelper.OWNED_STATUS:
                        // If there is no owner and no workgroup
                        if(obj.isNullQw_ownerid()) {
                            if(obj.isNullQw_workgroupid()) {
                                throw new EQLException(
                                        "Cannot save ticket without owner or workgroup.");
                            } else {
                                // There is no owner but we have a workgroup
                                obj.setQw_status(new Integer(
                                        TicketHelper.ASSIGNED_STATUS));
                                obj.setQw_dateassigned(now);
                            }
                            obj.setQw_dateowned(null);
                        } else {
                            long owner = obj.getQw_ownerid().longValue();
                            if(owner == user.getUserID()) {
                                obj.setQw_dateowned(now);
                            } else {
                                if(oldStatus != TicketHelper.ASSIGNED_STATUS) {
                                    obj.setQw_status(new Integer(
                                            TicketHelper.ASSIGNED_STATUS));
                                    obj.setQw_dateassigned(now);
                                } else {
                                    throw new EQLException(
                                            "Only owner can trigger ticket to owned status from assigned status.");
                                }
                            }
                        }
                        obj.setQw_datedelivered(null);
                        obj.setQw_resbuildversionid(null);
                        break;

                    case TicketHelper.NEW_STATUS:
                    case TicketHelper.RELEASE_CANDIDATE_STATUS:
                    case TicketHelper.UNREPRODUCIBLE_STATUS:
                    case TicketHelper.DUPLICATE_STATUS:
                    case TicketHelper.PARKED_STATUS:
                    case TicketHelper.CLIENT_ISSUE_STATUS:
                    case TicketHelper.TESTFAIL_STATUS:
                        break;

                    case TicketHelper.DELIVERED_STATUS:
                        if(obj.isNullQw_resbuildversionid()) {
                            throw new EQLException(
                                    "You must fill the following field: Resolved in Build");
                        }
                        obj.setQw_datedelivered(now);
                        break;

                    case TicketHelper.CLOSED_STATUS:
                        if(obj.isNullQw_reasoncode()) {
                            throw new EQLException(
                                    "You must fill the following field: Reason Code");
                        } else {
                            if(obj.getQw_reasoncode().intValue() == TicketHelper
                                    .RC_OTHER && obj.isNullQw_otherreason()) {
                                throw new EQLException(
                                        "You must fill the following field: Other reason");
                            }
                        }
                        obj.setQw_dateclosed(now);
                        // Figure the age of the call (in business hours)
                        //if( !obj.isNullDatereported() ) {
                        //    Date datereported = obj.getDatereported();
                        //    int timetoclose = ( int ) ( now.getTime() - datereported.getTime() ) / 1000;
                        //    obj.setTimetoclose( new Integer( timetoclose ) );
                        //}

                        // Now Check and set if closed on time accordingly
                        //Date mustresolveby = obj.getMustresolveby();
                        //if( mustresolveby != null && mustresolveby.getTime() < now.getTime() ) {
                        //    obj.setClosedintime( new Integer( 0 ) );
                        //} else {
                        //    obj.setClosedintime( new Integer( 1 ) );
                        //}
                        break;

                    default:
                        throw new IllegalStateException(
                                "Unsupported ticket status: " + ticketStatus);
                }
                obj.setQw_laststatuschanged(now);
            }
            obj.setQw_modifiedbyid(new Long(user.getUserID()));
            obj.setQw_datemodified(now);
        }

        if(getLogger().isInfoEnabled()) {
            INFO("TicketUpdate#beforeUpdate finished for ticket #" + ticketID
                    + ".");
            INFO("Time (ms) - " + (System.currentTimeMillis() - time));
        }

        // Ok.
        return CONTINUE;

    } // beforeUpdate()


    /* (non-Javadoc)
    * @see EntityUpdate#beforeDelete()
    */
    public int beforeDelete()
            throws EQLException {

        long time = System.currentTimeMillis();

        // Initialization.
        JEOManagerLocal jeoManager = (JEOManagerLocal)
                getCOM().getLocalObject(JNDINames.JEOManager,
                        JEOManagerLocalHome.class);
        LogonSession ls = getEUO().getSession().getLogonSession();

        // Get current ticket record.
        JEObjectHandler hnd = getJEOHandler(jeoManager,
                TicketObjectHandler.class);
        TicketObject obj = (TicketObject) hnd.getJEObject();

        // Get ticket ID.
        long callID = obj.getQw_ticketid().longValue();

        // Load linked inbox messages.
        //List inboxHndList = InboxObjectHandler.selectByLinkObj( jeoManager, ls, callID, null );
        //int size = ( inboxHndList == null ) ? 0 : inboxHndList.size();
        //for( int i = 0; i < size; i++ ) {
        // Unbind inbox message.
        //InboxObjectHandler inboxHnd = ( InboxObjectHandler ) inboxHndList.get( i );
        //InboxObject inbox = ( InboxObject ) inboxHnd.getJEObject();
        //inbox.setCall_id( null );
        //inboxHnd.commit();
        //}

        if(getLogger().isInfoEnabled()) {
            INFO("TicketUpdate#beforeDelete finished for ticket #" + callID
                    + ".");
            //INFO( "Unbound " + size + " inbox messages." );
            INFO("Time (ms) - " + (System.currentTimeMillis() - time));
        }

        return CONTINUE;

    } // beforeDelete()


    public void afterUpdate() throws EQLException {

        //long time = System.currentTimeMillis();
        JEObjectHandler eventHnd = null;
        TicketEventObject eventObj = null;

        // Initialization.
        JEOManagerLocal jeoManager = (JEOManagerLocal)
                getCOM().getLocalObject(JNDINames.JEOManager,
                        JEOManagerLocalHome.class);
        LogonSession ls = getEUO().getSession().getLogonSession();
        //User user = ls.getUser();

        // Get current ticket record.
        JEObjectHandler hnd = getJEOHandler(jeoManager,
                TicketObjectHandler.class);
        TicketObject ticketObj = (TicketObject) hnd.getJEObject();

        // New Ticket
        if(isNew()) {
            TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                    TicketEventHelper.TICKET_CREATED);
        } else {
            // Status change
            if(ticketObj.isChangedQw_status()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.STATUS_CHANGE);
            }
            // Priority change
            if(ticketObj.isChangedQw_priority()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.PRIORITY_CHANGE);
            }
            // Impact change
            if(ticketObj.isChangedQw_impact()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.IMPACT_CHANGE);
            }
            // Type change
            if(ticketObj.isChangedQw_type()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.TYPE_CHANGE);
            }
            // Owner change
            if(ticketObj.isChangedQw_ownerid()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.OWNER_CHANGE);
            }
            // Agent change
            if(ticketObj.isChangedQw_agentid()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.AGENT_CHANGE);
            }
            // Workgroup change
            if(ticketObj.isChangedQw_workgroupid()) {
                TicketEventHelper.createEvent(jeoManager, ls, ticketObj,
                        TicketEventHelper.WORKGROUP_CHANGE);
            }
        }
    }

}
