/* 
 *  ConsultForm.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.DestinationI;
import com.avaya.ccs.api.DestinationListI;
import com.avaya.ccs.api.enums.DestinationType;
import com.avaya.ccs.api.enums.InteractionType;
import com.avaya.ccs.core.EmailMedia;
import com.avaya.ccs.core.Media;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

/**
 * This form is used to display both the transfer and conference destinations.
 * In addition the form is used for free form dialing in both cases.
 */
public class ConsultForm {

    private final Stage form = new Stage();
    private static final Logger LOG = Logger.getLogger(ConsultForm.class);
    enum RelocationType {
    	Consult, Transfer
    }
    
    RelocationType relocationType;
    
    private final InteractionExecutor interactionExe;

    private final ObservableList<DestinationI> destinationsOL = FXCollections.observableArrayList();
    private String currentInteractionID;
    private ListView<DestinationI> destinationsLV = new ListView<>();
    private InteractionType interactionType; 
    private Media media; //needed for external transfers
	private MediaFormI mediaForm;
	private String agentSignature="";
	private boolean mediaSet;

   
    public ConsultForm(InteractionExecutor interactionExe, String css, InteractionType interactionType) {
        this.interactionExe = interactionExe;
        BorderPane consultBorder = new BorderPane();
        Scene consultScene = new Scene(consultBorder, 300, 400);
        consultScene.getStylesheets().add(css);
        form.setScene(consultScene);
        this.interactionType = interactionType;
        
    }
    
    public void show() {
        form.show();
    }
    
    public void setCurrentInteractionId(String id) {
    	this.currentInteractionID=id;
    }

    public void updateDestinationList(String interactionID, DestinationListI list) {
        String methodName = "updateDestinationList ";
        //TODO conroy1 convoluted: make simpler. Can remove this block when am sure that Forms and Interactions are properly integrated
        if (interactionID.equals(currentInteractionID)) {
        	LOG.info(methodName + "Contact ID:" + interactionID + " updating list with " + list.getDestinations().size()
                    + " items");
        } else { 
            LOG.error(methodName + "Contact ID:" + interactionID + " does not match current contactID:"
                    + currentInteractionID);
            return;
        }
        /////////
        
        //if this is a Transfers form, add all destinations.
        //if it's a Consult form, only add Agent destinations
        
        if  (relocationType==RelocationType.Transfer) {
        	LOG.debug(methodName + "Transfer");
        	destinationsOL.addAll(list.getDestinations());
        } else if (relocationType==RelocationType.Consult) {
        	LOG.debug(methodName + " Consult");
        	for (DestinationI item:list.getDestinations()) {
            	if  (item.getDestinationType() == DestinationType.Agent) {
            		destinationsOL.add(item);
            	}
            }
        } else {
        	LOG.error(methodName, " Unsupported relocation type. Destinations: "+list);
        }
    }

    public void initializeTransferForm(Data interactionData) {
    	initializeForm(true, interactionData);
    }

    public void initializeConsultForm(Data interactionData) {
        initializeForm(false, interactionData);
    }

    private void initializeForm(boolean transfer, Data interactionData) {
        if (transfer) {
        	this.relocationType=RelocationType.Transfer;
            
        } else {
        	this.relocationType=RelocationType.Consult;
        }
    
        
        form.titleProperty().set(relocationType.name());
        
        destinationsOL.clear();
        BorderPane bp = (BorderPane) form.sceneProperty().get().getRoot();
        destinationsLV.setItems(destinationsOL);
        // We want the list to display the name and code only
        destinationsLV.setCellFactory(new Callback<ListView<DestinationI>, ListCell<DestinationI>>() {
            @Override
            public ListCell<DestinationI> call(ListView<DestinationI> list) {
                return new ConsultForm.CodeCell();
            }
        });

        // Only enable the ok button when a selection is made....
        Button dialDestinationButton = new Button("Dial Destination");
        dialDestinationButton.setDisable(true);

        destinationsLV.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<DestinationI>() {
            @Override
            public void changed(ObservableValue<? extends DestinationI> observable, DestinationI oldValue,
                    DestinationI newValue) {
                if (newValue != null) {
                    dialDestinationButton.setDisable(false);
                }
            }
        });

        bp.setCenter(destinationsLV);

        dialDestinationButton.getStyleClass().add("consultFormButtons");
        if (transfer) {
            dialDestinationButton.setOnAction((ActionEvent t) -> {
                String methodName = "dialDestinationButton() ";
                DestinationI selectedDestination = destinationsLV.getSelectionModel().getSelectedItem();
                
                
                if (selectedDestination != null) {
                    LOG.info(methodName + "Transfer:InteractionID:" + currentInteractionID + " Desination:"
                            + selectedDestination);
                    if (interactionType==InteractionType.VoiceInteraction) {
                    	this.interactionExe.initiateTransferToConsultDestination(currentInteractionID, selectedDestination);
                    } else if (interactionType==InteractionType.EmailInteraction) {
                    	this.interactionExe.transferToConsultDestination(currentInteractionID, selectedDestination);
                    } else if (interactionType==InteractionType.ChatInteraction) {
                    		if (relocationType.equals(RelocationType.Consult)) {
                    			interactionExe.initConference(currentInteractionID, selectedDestination.getNumber());
                    		} else {
                    			interactionExe.transferToConsultDestination(currentInteractionID, selectedDestination);
                    		}
                    } else {
                    	LOG.warn(methodName, "Not implemented");
                    }

                } else {
                    LOG.error(methodName + "Selected destination is null");
                }
                form.close();
                mediaForm.close();
            });
        } else {
            dialDestinationButton.setOnAction((ActionEvent t) -> {
                String methodName = "dialDestinationButton";
                DestinationI selectedDestination = destinationsLV.getSelectionModel().getSelectedItem();

                if (selectedDestination != null) {
                    LOG.info(methodName + "Conference:InteractionID:" + currentInteractionID + " Desination:"
                            + selectedDestination);
                   if (interactionType==InteractionType.VoiceInteraction)
                	   this.interactionExe.conferenceToConsultDestination(currentInteractionID, selectedDestination);
                   else if (interactionType==InteractionType.ChatInteraction) {
                	   if (relocationType.equals(RelocationType.Consult)) {
	               			interactionExe.initConference(currentInteractionID, selectedDestination.getNumber());
                	   }
                	       
                } 
              
            	
            }
                else {
                    LOG.error(methodName + "Selected destination is null");
                }
                form.close();
            });
        }

        Button cancelButton = new Button("Cancel");
        cancelButton.getStyleClass().add("consultFormButtons");
        cancelButton.setOnAction((ActionEvent t) -> {
            LOG.info("CancelButton");
            form.close();
        });
        
        HBox hbuttonbox = new HBox();
        hbuttonbox.getChildren().addAll(dialDestinationButton, cancelButton);
        
        // Free form number handling
        HBox freeFormBox = new HBox();
        TextField freeFormDest = new TextField();
        Button freeFormTransferButton = new Button("Send External");
        freeFormTransferButton.getStyleClass().add("consultFormButtons");
        
        if (transfer) {
            freeFormTransferButton.setOnAction((ActionEvent t) -> {
            	if (interactionType==InteractionType.VoiceInteraction) {
                    String id = interactionData.getId();
                    String destination = freeFormDest.getText();
                    interactionExe.initTransfer(id, destination);
                    form.close();
            	} else if (interactionType==InteractionType.EmailInteraction){
            		
            		String id = interactionData.getId();
                    String destination = freeFormDest.getText();
                    EmailForm emailForm = (EmailForm)mediaForm;
                    EmailMedia email = (EmailMedia) media;
                    boolean isHtml=true; //hardcoding to true for the moment TODO
                    email.reply(
                    		destination, 
                			"", 
                			"", 
                			emailForm.getSubjectField().getText(), 
                			emailForm.getBodyHtml(), 
                			"", 
                			true,
                			isHtml
                			); 
                    
                    form.close();
                    emailForm.close();
            	}
            	
            });
        } else {
            freeFormTransferButton.setOnAction((ActionEvent t) -> {
                String id = interactionData.getId();
                String destination = freeFormDest.getText();
                interactionExe.initConference(id, destination);
                form.close();
            });
        }
        // Disable the free dial button until there is a number entered
        freeFormTransferButton.setDisable(true);
        freeFormDest.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {

                freeFormTransferButton.setDisable(newValue.isEmpty());
            }
        });

        freeFormBox.getChildren().addAll(freeFormDest, freeFormTransferButton);
        VBox v = new VBox();
        v.getChildren().addAll(freeFormBox, hbuttonbox);
        bp.setBottom(v);	
    }
    
    
    public void setInteractionMedia(Media media) {
    	if (media!=null) {
    		this.media=media;
        	this.mediaSet=true;
    	}    	
    }
    
    public boolean isMediaSet() {
    	return mediaSet;
    }    

	private static class CodeCell extends ListCell<DestinationI> {

        @Override
        public void updateItem(DestinationI item, boolean empty) {
            super.updateItem(item, empty);
            if (item != null) {
                setText(item.getName() + ":" + item.getNumber() + ":" + item.getDestinationType().name());
            }
        }
    }

	public void setMediaForm(MediaFormI emailForm) {
		this.mediaForm=emailForm;
		
	}

	public void setAgentSignature(String agentSignature) {
		this.agentSignature=agentSignature;
		
	}
}
