/* 
 *  UserDataGUI.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 java.util.List;
import java.util.Optional;

import com.avaya.ccs.api.CodeListI;
import com.avaya.ccs.api.ContactCenterCodeI;
import com.avaya.ccs.api.enums.CodeType;
import com.avaya.ccs.api.enums.ContactType;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.MenuItem;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

/**
 * This class is responsible for all the user related GUI components the only
 * entry into this class should be to add new users or update existing ones.
 */
public class UserDataGUI extends ComboDataGUI {

    private final HBox userButtonsHolder = new HBox();
    private final HBox userStatusHolder = new HBox();
    private final VBox userHolder = new VBox();

    
    private final Button buttonAgentLogin;
    private final Button buttonAgentReady;
    private final Button buttonAgentNotReady;
    private final Button buttonAgentNotReadyWithReason;
    private final Button buttonAgentACW;
    private final Button originateEmailButton;
    private final Button agentSignatureButton;
    
    InteractionExecutor interactionExe;

    private final Label agentStatus;
    private final Label pomStatus;
    private final Label userSyncStatus;

    private final String goReadyButtonText = "Ready";
    private final String goNotReadyButtonText = "NotReady";
    private final String goNotReadyWithReasonButtonText = "NotReadyWithReason";
    private final String goACWButtonText = "ACW";

    private final String loginButtonText = "Login";
    private final String logoutButtonText = "Logout";

    private final CodeSelectionForm codeSelection;
    private static final Logger LOG = Logger.getLogger(UserDataGUI.class);

    public UserDataGUI(ClientSessionExecutor clientSessionExe, UserExecutor userExe, InteractionExecutor interactionExe, String css,
            CodeSelectionForm codeSelection) {
        super(LOG);
        this.codeSelection = codeSelection;
        setDetailsForm(new UserDetailsForm(userExe, css, this));

        userButtonsHolder.getStyleClass().add("hbox");
        userStatusHolder.getStyleClass().add("hbox");
        
        this.interactionExe=interactionExe;

        buttonAgentLogin = new Button(loginButtonText);
        buttonAgentLogin.getStyleClass().add("agentButton");
        buttonAgentLogin.setOnAction((ActionEvent e) -> {
            String methodName = "agentLoginButton() ";

            if (getUser(getItemSelection().getValue()).canLogout()) {
                userExe.logout(getUser(getItemSelection().getValue()).getId());
            } else if (getUser(getItemSelection().getValue()).canLogin()) {
                Dialog<LoginDetails> dialog = new Dialog<>();
                dialog.setTitle("Agent Login");

                ButtonType signinButtonType = new ButtonType("Login", ButtonBar.ButtonData.OK_DONE);
                dialog.getDialogPane().getButtonTypes().addAll(signinButtonType, ButtonType.CANCEL);

                GridPane grid = new GridPane();
                grid.getStyleClass().add("dialog");

                TextField dialogUsername = new TextField();
                dialogUsername.setPromptText("AgentID");
                dialogUsername.setText(getUser(getItemSelection().getValue()).getLoginId());
                dialogUsername.setEditable(false);
                PasswordField dialogPassword = new PasswordField();
                dialogPassword.setPromptText("Password");

                grid.add(new Label("AgentID:"), 0, 0);
                grid.add(dialogUsername, 1, 0);
                grid.add(new Label("Password:"), 0, 1);
                grid.add(dialogPassword, 1, 1);

                // In a POM environment a zone must be selected, add a
                // combobox here with the list of zones
                List<String> zones = getUser(getItemSelection().getValue()).getPomZones();
                ComboBox<String> zoneList = new ComboBox<String>(FXCollections.observableList(zones));
                zoneList.getSelectionModel().selectFirst();

                grid.add(new Label("POM Zone:"), 0, 2);
                grid.add(zoneList, 1, 2);

                dialog.getDialogPane().setContent(grid);

                Platform.runLater(() -> dialogUsername.requestFocus());

                // Convert the result to a username-password-pair when the
                // login button is clicked.
                dialog.setResultConverter(dialogButton -> {
                    if (dialogButton == signinButtonType) {
                        return new LoginDetails(dialogUsername.getText(), dialogPassword.getText(),
                                zoneList.getValue());
                    }
                    return null;
                });

                Optional<LoginDetails> result = dialog.showAndWait();

                result.ifPresent(loginDetails -> {
                    LOG.info(methodName + "Username:" + loginDetails.username + " Password length:"
                            + loginDetails.password.length() + " zone:"
                            + ((loginDetails.zone == null) ? "NULL" : loginDetails.zone));
                    userExe.login(getUser(getItemSelection().getValue()).getId(), loginDetails.password,
                            loginDetails.zone);
                });
            }
        });

        buttonAgentReady = new Button(goReadyButtonText);
        buttonAgentReady.getStyleClass().add("agentButton");
        buttonAgentReady.setOnAction((ActionEvent e) -> {
            String userId = getUser(getItemSelection().getValue()).getId();
            LOG.info("ReadyButton() UserID:" + userId);
            userExe.ready(userId);
        });

        buttonAgentNotReady = new Button(goNotReadyButtonText);
        buttonAgentNotReady.setOnAction((ActionEvent e) -> {
            String userId = getUser(getItemSelection().getValue()).getId();
            LOG.info("NotReadyButton() UserID:" + userId);
            userExe.notReady(userId, null);
        });

        buttonAgentNotReadyWithReason = new Button(goNotReadyWithReasonButtonText);
        buttonAgentNotReadyWithReason.setOnAction((ActionEvent e) -> {
            LOG.info("NotReadyWithReasonButton() ");
            clientSessionExe.getSessionCodes(CodeType.NRRC);
            // Display code selection form, this will initiall be blank
            codeSelection.show();
        });

        buttonAgentACW = new Button(goACWButtonText);
        buttonAgentACW.setOnAction((ActionEvent e) -> {
            LOG.info("ACWButton() ");
            clientSessionExe.getSessionCodes(CodeType.ACW);
            // Display code selection form, this will initiall be blank
            codeSelection.show();
        });
        
        
        originateEmailButton = new Button("New Email");
        originateEmailButton.getStyleClass().add("agentButton");
        originateEmailButton.setOnAction((ActionEvent e) -> {
        	userExe.originateEmail(getItemSelection().getValue());
        });
        
        agentSignatureButton= new Button("Edit signature");
        agentSignatureButton.getStyleClass().add("agentButton");
        agentSignatureButton.setOnAction((ActionEvent e) -> {
	        	AgentSignatureForm newForm= new AgentSignatureForm(getItemSelection().getValue(), userExe, getUser(getItemSelection().getValue()).getAgentSignature(), css);
	        	newForm.show();
	    });

        userButtonsHolder.getChildren().addAll(getItemSelection(), buttonAgentLogin, buttonAgentReady,
                buttonAgentNotReady, buttonAgentNotReadyWithReason, buttonAgentACW,
//                agentSignatureButton, 
                originateEmailButton
                );
        userButtonsHolder.setAlignment(Pos.CENTER_LEFT);

        agentStatus = new Label();
        pomStatus = new Label();
        userSyncStatus = new Label();
        agentStatus.setPrefWidth(80);
        pomStatus.setPrefWidth(120);
        userStatusHolder.getChildren().addAll(agentStatus, pomStatus, userSyncStatus);
        userStatusHolder.setAlignment(Pos.CENTER_LEFT);

        userHolder.getChildren().addAll(userButtonsHolder, userStatusHolder);
        redrawControls();
    }

    public MenuItem getMenuItem() {
        return getDetailsForm().getMenuItem();
    }

    // Return the current user selection or a dummy value if there is none....
    private UserData getCurrentUserSelection() {
        String methodName = "getCurrentUserSelection() ";
        Data currentUser = getCurrentItemSelection();

        if (currentUser != null) {
            return (UserData) currentUser;
        } else {
            LOG.trace(methodName + "current selection is NULL, returning blank");
            return new UserData(null);
        }
    }

    public UserData getUser(String id) {
        return (UserData) getItem(id);
    }

    public VBox getUserControls() {
        return userHolder;
    }

    @Override
    protected void redrawControls() {
        String methodName = "redrawControls() ";

        UserData user = getCurrentUserSelection();
        LOG.trace(methodName + " UserID:" + user.getId());

        String status = user.getState().toString();
        if (user.getCode() != null) {
            status += ":" + user.getCode().getName() + ":" + user.getCode().getNumber();
        }
        this.agentStatus.setText(status);
        this.agentStatus.setPrefWidth(10 * (status.length() + 1));

        String pomState = "";
        if (user.isPomNailedUp()) {
            pomState += "NailedUP";
        } else {
            pomState += "NotNailedUP";
        }

        this.pomStatus.setText(pomState);
        this.pomStatus.setPrefWidth(10 * (pomState.length() + 1));
        // Only display the POM nailed up status if the user has the POM contact
        // type
        this.pomStatus.setVisible(user.getContactTypes().contains(ContactType.POM_Outbound));

        this.userSyncStatus.setText(user.getUserSyncStatus().name());

        switch (user.getUserSyncStatus()) {
        case LoginRequired:
        case LogoutRequired:
        case ToggleReady:
        case ProviderUnavailable:
            this.userSyncStatus.setVisible(true);
            JavaFXRefClient.UpdateStatus(user.getId() + ":" + user.getUserSyncMessage());
            break;
        case Synchronised:
            // Want to clear the previous status if its still there
            if (JavaFXRefClient.getStatus().contains(user.getId()))
                JavaFXRefClient.UpdateStatus("");
        case NotApplicable:
        case Unknown:
        default:
            this.userSyncStatus.setVisible(false);
            break;
        }

        if (user.canLogin()) {
            buttonAgentLogin.setText(loginButtonText);
            buttonAgentLogin.setDisable(false);
        } else if (user.canLogout()) {
            buttonAgentLogin.setText(logoutButtonText);
            buttonAgentLogin.setDisable(false);
        } else {
            buttonAgentLogin.setDisable(true);
        }

        buttonAgentReady.setDisable(!user.canReady());
        buttonAgentNotReady.setDisable(!user.canNotReady());
        buttonAgentNotReadyWithReason.setDisable(!user.canNotReady());
        buttonAgentACW.setDisable(!user.canAfterCallWork());
        originateEmailButton.setDisable(
        		!(user.getContactTypes().contains(ContactType.EMail) && user.canLogout())
        		);      
    }
    
    public void setAgentNotReady() {
    	LOG.debug("setAgentNotReady() fired");
    	buttonAgentNotReady.fire();
    }

    static class CodeCell extends ListCell<ContactCenterCodeI> {
        @Override
        public void updateItem(ContactCenterCodeI item, boolean empty) {
            super.updateItem(item, empty);
            if (item != null) {
                setText(item.getName() + ":" + item.getNumber().toString());
            }
        }
    }

    public void updateCodeSectionForm(CodeListI codes) {
        codeSelection.updateCodeSectionForm(codes, getCurrentUserSelection().getId());
    }

    public void UpdateUserData(List<UserData> data) {
        // Need to convert to use data objects before setting
        ObservableList<Data> newData = FXCollections.observableArrayList();
        newData.addAll(data);
        this.update(newData);
    }

    public void UpdateUserData(UserData data) {
        this.update(data);
    }

    private class LoginDetails {

        public String username;
        public String password;
        public String zone;

        public LoginDetails(String username, String password, String zone) {
            this.username = username;
            this.password = password;
            this.zone = zone;
        }

    }
}
