/* 
 *  MonitoredInteractionData.java
 * 
 *  Copyright 2016 Avaya Inc. All Rights Reserved.
 * 
 *  Usage of this source is bound to the terms described
 *  in AvayaLicenseSDK.rtf.
 * 
 *  Avaya - Confidential & Proprietary. Use pursuant to your signed agreement
 *  or Avaya Policy
 * 
 */
package com.avaya.ccs.javafxrefclient;

import com.avaya.ccs.api.ContactCenterCodeI;
import com.avaya.ccs.api.CustomerDetailsI;
import com.avaya.ccs.api.DataI;
import com.avaya.ccs.api.MonitoredInteractionI;
import com.avaya.ccs.api.IntrinsicI;
import com.avaya.ccs.api.enums.ContactType;
import com.avaya.ccs.api.enums.InteractionState;
import com.avaya.ccs.api.enums.StateReason;
import com.avaya.ccs.api.exceptions.ObjectInvalidException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javafx.util.Pair;

public class MonitoredInteractionData extends Data implements InteractionDataI {

    // Capabilities
    private boolean canObserve = false;
    private boolean canBargeIn = false;
    private boolean canWhisper = false;

    // Properties
    private ContactCenterCodeI activityCode = null;
    private String activityCodeNumber = null;
    private String address = "";
    private String addressName = "";
    private String calledAddress = "";
    private String calledAddressName = "";
    private String callingAddress = "";
    private String callingAddressName = "";
    private String contactID = "";
    private ContactType contactType = ContactType.Unknown;
    private DataI data = null;
    private String id = "";
    private List<IntrinsicElement> intrinsics = new LinkedList<>();
    private String mainContactID = "";
    private String originalDestination = "";
    private String skillset = "";
    private InteractionState state = InteractionState.Unknown;
    private StateReason stateReason = StateReason.Unknown;
    private String uui = "";
    private String monitoredUserID = "";
    private boolean monitored = false;
    private boolean multimedia = false;

    private InteractionData supervisorInteraction = null;
    private static final Logger LOG = Logger.getLogger(MonitoredInteractionData.class);

    public MonitoredInteractionData(MonitoredInteractionI interaction) {
        String methodName = "MonitoredInteractionData() ";
        if (interaction != null) {
            try {
                // Capabilities
                canObserve = interaction.canObserve();
                canBargeIn = interaction.canBargeIn();
                canWhisper = interaction.canWhisper();

                // Properties
                activityCode = interaction.getActivityCode();
                if (activityCode != null) {
                    activityCodeNumber = activityCode.getNumber().toString();
                }
                address = interaction.getAddress();
                addressName = interaction.getAddressName();
                calledAddress = interaction.getCalledAddress();
                calledAddressName = interaction.getCalledAddressName();
                callingAddress = interaction.getCallingAddress();
                callingAddressName = interaction.getCallingAddressName();
                contactID = interaction.getContactId();
                contactType = interaction.getContactType();
                data = interaction.getData();
                id = interaction.getId();
                intrinsics = buildIntrinsicsElmentList(interaction);
                mainContactID = interaction.getMainContactId();
                originalDestination = interaction.getOriginalDestination();
                skillset = interaction.getSkillset();
                state = interaction.getState();
                stateReason = interaction.getStateReason();
                uui = interaction.getUUI();
                monitoredUserID = interaction.getMonitoredUserId();
                monitored = interaction.isMonitored();
                multimedia = interaction.isMultimedia();

            } catch (ObjectInvalidException ex) {
                LOG.error(methodName, "ObjectInvalidException while accessing MonitoredInteractionData", ex);
                canObserve = false;
                canBargeIn = false;
                canWhisper = false;

                // Properties
                activityCode = null;
                activityCodeNumber = null;
                address = "";
                addressName = "";
                calledAddress = "";
                calledAddressName = "";
                callingAddress = "";
                callingAddressName = "";
                contactID = "";
                contactType = ContactType.Unknown;
                data = null;
                id = "";
                intrinsics = new LinkedList<>();
                mainContactID = "";
                originalDestination = "";
                skillset = "";
                state = InteractionState.Unknown;
                stateReason = StateReason.Unknown;
                uui = "";
                monitoredUserID = "";
                monitored = false;
                multimedia = false;
            }
        }
    }

    public MonitoredInteractionData(String id, boolean deleted) {
        this.id = id;
        this.setDeleted(deleted);
    }

    public String toString() {
        String str = "ID:" + id;
        // Properties
        str += " activityCode:" + activityCode + " activityCodeNumber:" + activityCodeNumber + " address:" + address
                + " addressName:" + addressName + " calledAddress:" + calledAddress + " calledAddressName:"
                + calledAddressName + " callingAddress:" + callingAddress + " callingAddressName:" + callingAddressName;
        str += " contactID:" + contactID + " contactType:" + contactType + " mainContactID:" + mainContactID
                + " originalDestination:" + originalDestination + " skillset:" + skillset + " state:" + state.name()
                + " stateReason:" + stateReason.name() + " monitoredUserID:" + monitoredUserID + " monitored:"
                + monitored + " multimedia:" + multimedia;
        // Capabilities
        str += " canObserve:" + canObserve + " canBargeIn:" + canBargeIn + " canWhisper" + canWhisper;
        return str;
    }

    @Override
    public List<Pair<String, String>> getProperties() {
        // Properties
        List<Pair<String, String>> properties = new LinkedList<>();
        properties.add(new Pair<String, String>("ID", this.getId()));
        String actCode = "NONE";
        if (this.activityCode != null) {
            actCode = this.activityCode.getName() + ":" + this.activityCode.getNumber();
        }

        properties.add(new Pair<String, String>("ActivityCode", actCode));
        properties.add(new Pair<String, String>("Address", this.getAddress()));
        properties.add(new Pair<String, String>("AddressName", this.getAddressName()));
        properties.add(new Pair<String, String>("CalledAddress", this.getCalledAddress()));
        properties.add(new Pair<String, String>("CalledAddressName", this.getCalledAddressName()));
        properties.add(new Pair<String, String>("CallingAddress", this.getCalledAddress()));
        properties.add(new Pair<String, String>("CallingAddressName", this.getCallingAddressName()));
        properties.add(new Pair<String, String>("ContactId", this.getContactID()));
        properties.add(new Pair<String, String>("ContactType", this.getContactType().name()));
        properties.add(new Pair<String, String>("MainContactId", this.getMainContactID()));
        properties.add(new Pair<String, String>("OriginalDestination", this.getOriginalDestination()));
        properties.add(new Pair<String, String>("Skillset", this.getSkillset()));

        properties.add(new Pair<String, String>("MonitoredUserId", this.getMonitoredUserID()));
        properties.add(new Pair<String, String>("isMonitored", Boolean.toString(this.isMonitored())));
        properties.add(new Pair<String, String>("isMultimedia", Boolean.toString(this.isMultimedia())));

        properties.add(new Pair<String, String>("State", this.getState().name()));
        properties.add(new Pair<String, String>("StateReason", this.getStateReason().name()));

        return properties;
    }

    @Override
    public List<Pair<String, Boolean>> getCaps() {
        List<Pair<String, Boolean>> caps = new LinkedList<>();
        caps.add(new Pair<String, Boolean>("canObserve", this.canObserve()));
        caps.add(new Pair<String, Boolean>("canBargeIn", this.canBargeIn()));
        caps.add(new Pair<String, Boolean>("canWhisper", this.canWhisper()));

        return caps;
    }

    private List<IntrinsicElement> buildIntrinsicsElmentList(MonitoredInteractionI interaction) {
        List<IntrinsicElement> l = new ArrayList<>();
        try {
            for (IntrinsicI i : interaction.getIntrinsics()) {
            	 l.add(new IntrinsicElement(i.getName(), i.getValue()));
            }
        } catch (ObjectInvalidException e) {
            return new ArrayList<>();
        }
        return l;
    }

    @Override
    public String getId() {
        return this.id;
    }

    public boolean canObserve() {

        return canObserve;

    }

    /**
     * Returns canObserve if the supervisor is not already on the call, false
     * otherwise
     * 
     * @return
     */
    public boolean canObserveCalculated() {
        if (this.supervisorInteraction == null) {
            return canObserve;
        }
        return false;
    }

    /**
     * Returns canBargeIn if there is an observe leg or whisper leg, false
     * otherwise
     * 
     * @return
     */
    public boolean canBargeInCalculated() {
        if (this.supervisorInteraction != null
                && (this.supervisorInteraction.getParticipationReason().equals(StateReason.Observe)
                        || this.supervisorInteraction.getParticipationReason().equals(StateReason.Whisper))) {
            return canBargeIn;
        }
        return false;
    }

    public boolean canBargeIn() {
        return canBargeIn;
    }

    /**
     * Returns canWhisper if there is an observe leg, false otherwise
     * 
     * @return
     */
    public boolean canWhisperCalculated() {
        if (this.supervisorInteraction != null
                && this.supervisorInteraction.getParticipationReason().equals(StateReason.Observe)) {
            return canWhisper;
        }
        return false;
    }

    public boolean canWhisper() {
        return canWhisper;

    }

    @Override
    public boolean canSetIntrinsic() {
        return contactType.equals(ContactType.Voice);
    }

    public boolean canGetIntrinsic() {
        return contactType.equals(ContactType.Voice);
    }

    public boolean canGetUUI() {
        return contactType.equals(ContactType.Voice);
    }

    public boolean canGetData() {
        return contactType.equals(ContactType.Voice);
    }

    public ContactCenterCodeI getActivityCode() {
        return activityCode;
    }

    public String getAddress() {
        return address;
    }

    public String getAddressName() {
        return addressName;
    }

    public String getCalledAddress() {
        return calledAddress;
    }

    public String getCalledAddressName() {
        return calledAddressName;
    }

    public String getCallingAddress() {
        return callingAddress;
    }

    public String getCallingAddressName() {
        return callingAddressName;
    }

    public String getContactID() {
        return contactID;
    }

    public ContactType getContactType() {
        return contactType;
    }

    @Override
    public DataI getData() {
        return data;
    }

    @Override
    public List<IntrinsicElement> getIntrinsics() {
        return intrinsics;
    }

    public String getMainContactID() {
        return mainContactID;
    }

    public String getOriginalDestination() {
        return originalDestination;
    }

    public String getSkillset() {
        return skillset;
    }

    public InteractionState getState() {
        return state;
    }

    public StateReason getStateReason() {
        return stateReason;
    }

    public String getUui() {
        return uui;
    }

    public String getMonitoredUserID() {
        return monitoredUserID;
    }

    public String getActivityCodeNumber() {
        return activityCodeNumber;
    }

    public boolean isMonitored() {
        return monitored;
    }

    public boolean isMultimedia() {
        return multimedia;
    }

    @Override
    public boolean canSetUUI() {
        return false;
    }

    @Override
    public boolean canAddAgentNote() {
        return false;
    }

    @Override
    public List<String> getAgentNotes() {
        List<String> empty = new ArrayList<>();
        return empty;
    }

    @Override
    public boolean canGetCustomerDetails() {
        return false;
    }

    @Override
    public boolean canUpdateCustomerName() {
        return false;
    }

    @Override
    public boolean canUpdateCustomerEmail() {
        return false;
    }

    @Override
    public boolean canUpdateCustomerPhone() {
        return false;
    }

    @Override
    public boolean canUpdateCustomerAddress() {
        return false;
    }

    @Override
    public CustomerDetailsI getCustomerDetails() {
        throw new UnsupportedOperationException("Customer Details are not supported on monitored interactions");
    }

    @Override
    public void update(Data newData) {
        MonitoredInteractionData newMonitoredInteractionData = (MonitoredInteractionData) newData;
        // Capabilities
        this.canObserve = newMonitoredInteractionData.canObserve();
        this.canBargeIn = newMonitoredInteractionData.canBargeIn();
        this.canWhisper = newMonitoredInteractionData.canWhisper();

        // Properties
        this.activityCode = newMonitoredInteractionData.getActivityCode();
        this.activityCodeNumber = newMonitoredInteractionData.getActivityCodeNumber();
        this.address = newMonitoredInteractionData.getAddress();
        this.addressName = newMonitoredInteractionData.getAddressName();
        this.calledAddress = newMonitoredInteractionData.getCalledAddress();
        this.calledAddressName = newMonitoredInteractionData.getCalledAddressName();
        this.callingAddress = newMonitoredInteractionData.getCallingAddress();
        this.callingAddressName = newMonitoredInteractionData.getCallingAddressName();
        this.contactID = newMonitoredInteractionData.getContactID();
        this.contactType = newMonitoredInteractionData.getContactType();
        this.data = newMonitoredInteractionData.getData();
        this.id = newMonitoredInteractionData.getId();
        this.intrinsics = newMonitoredInteractionData.getIntrinsics();
        this.mainContactID = newMonitoredInteractionData.getMainContactID();
        this.originalDestination = newMonitoredInteractionData.getOriginalDestination();
        this.skillset = newMonitoredInteractionData.getSkillset();
        this.state = newMonitoredInteractionData.getState();
        this.stateReason = newMonitoredInteractionData.getStateReason();
        this.uui = newMonitoredInteractionData.getUui();
        this.monitoredUserID = newMonitoredInteractionData.getMonitoredUserID();
        this.monitored = newMonitoredInteractionData.isMonitored();
        this.multimedia = newMonitoredInteractionData.isMultimedia();
    }

    public void updateSupervisorInteraction(InteractionData interaction) {
        if (interaction == null || interaction.isDeleted()) {
            this.supervisorInteraction = null;
        } else {
            this.supervisorInteraction = interaction;
        }
    }
}
