/* 
 *  DtmfKeypad.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.function.UnaryOperator;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class DtmfKeypad {

    private InteractionExecutor interactionExe = null;
    private Stage theStage = null;
    private Scene theScene = null;
    private GridPane gridPane = null;
    private Button dtmf1, dtmf2, dtmf3, dtmf4, dtmf5, dtmf6, dtmf7, dtmf8, dtmf9, dtmf0;
    private Button dtmfStar, dtmfHash, dtmfSend;
    private TextField sentTones, typedTones;
    private String interactionId = null;

    private static final Logger LOG = Logger.getLogger(DtmfKeypad.class);

    private static final Integer BUTTONWIDTH = 45;
    private static final Integer BUTTONHEIGHT = 45;

    public Stage getStage() {
        return theStage;
    }

    public void show(String interactionId) {
        theStage.show();
        theStage.requestFocus();
        typedTones.requestFocus();
        this.interactionId = interactionId;
    }

    public void hide() {
        theStage.hide();
    }

    public DtmfKeypad(InteractionExecutor interactionExe) {
        this.interactionExe = interactionExe;
        gridPane = new GridPane();
        gridPane.setHgap(3);
        gridPane.setVgap(3);
        gridPane.setPadding(new Insets(5, 5, 5, 5));
        gridPane.setMinWidth(110);
        gridPane.setMinHeight(150);

        createDtmfGrid();
        this.theScene = new Scene(gridPane);
        this.theStage = new Stage(StageStyle.UTILITY);
        this.theStage.setScene(theScene);
        this.theStage.setTitle("DTMF Keypad");
        this.theStage.setOnCloseRequest(event -> {
            sentTones.clear();
        });
    }

    private void createDtmfGrid() {
        dtmf1 = new Button("1");
        dtmf1.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf1.setOnAction((ActionEvent e) -> {
            LOG.info("1()");
            dtmfButtonClicked(e);
        });

        dtmf2 = new Button("2");
        dtmf2.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf2.setOnAction((ActionEvent e) -> {
            LOG.info("2()");
            dtmfButtonClicked(e);
        });

        dtmf3 = new Button("3");
        dtmf3.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf3.setOnAction((ActionEvent e) -> {
            LOG.info("3()");
            dtmfButtonClicked(e);
        });

        dtmf4 = new Button("4");
        dtmf4.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf4.setOnAction((ActionEvent e) -> {
            LOG.info("4()");
            dtmfButtonClicked(e);
        });

        dtmf5 = new Button("5");
        dtmf5.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf5.setOnAction((ActionEvent e) -> {
            LOG.info("5()");
            dtmfButtonClicked(e);
        });

        dtmf6 = new Button("6");
        dtmf6.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf6.setOnAction((ActionEvent e) -> {
            LOG.info("6()");
            dtmfButtonClicked(e);
        });

        dtmf7 = new Button("7");
        dtmf7.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf7.setOnAction((ActionEvent e) -> {
            LOG.info("7()");
            dtmfButtonClicked(e);
        });

        dtmf8 = new Button("8");
        dtmf8.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf8.setOnAction((ActionEvent e) -> {
            LOG.info("8()");
            dtmfButtonClicked(e);
        });

        dtmf9 = new Button("9");
        dtmf9.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf9.setOnAction((ActionEvent e) -> {
            LOG.info("9()");
            dtmfButtonClicked(e);
        });

        dtmf0 = new Button("0");
        dtmf0.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmf0.setOnAction((ActionEvent e) -> {
            LOG.info("0()");
            dtmfButtonClicked(e);
        });

        dtmfStar = new Button("*");
        dtmfStar.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmfStar.setOnAction((ActionEvent e) -> {
            LOG.info("*()");
            dtmfButtonClicked(e);
        });

        dtmfHash = new Button("#");
        dtmfHash.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT);
        dtmfHash.setOnAction((ActionEvent e) -> {
            LOG.info("#()");
            dtmfButtonClicked(e);
        });

        dtmfSend = new Button(">>>");
        dtmfSend.setPrefSize(BUTTONWIDTH, BUTTONHEIGHT - 20);
        dtmfSend.setTooltip(new Tooltip("Send manual tones"));
        dtmfSend.setOnAction((ActionEvent e) -> {
            LOG.info("Send()");
            dtmfButtonClicked(e);
        });

        UnaryOperator<TextFormatter.Change> filter = new UnaryOperator<TextFormatter.Change>() {

            @Override
            public TextFormatter.Change apply(TextFormatter.Change t) {

                if (t.isReplaced()) {
                    if (t.getText().matches("[^0-9*#]")) {
                        t.setText(t.getControlText().substring(t.getRangeStart(), t.getRangeEnd()));
                    }
                }

                if (t.isAdded()) {
                    if (t.getText().matches("[^0-9*#]")) {
                        t.setText("");
                    }
                }

                return t;
            }
        };

        gridPane.add(dtmf1, 0, 0);
        gridPane.add(dtmf2, 1, 0);
        gridPane.add(dtmf3, 2, 0);
        gridPane.add(dtmf4, 0, 1);
        gridPane.add(dtmf5, 1, 1);
        gridPane.add(dtmf6, 2, 1);
        gridPane.add(dtmf7, 0, 2);
        gridPane.add(dtmf8, 1, 2);
        gridPane.add(dtmf9, 2, 2);
        gridPane.add(dtmf0, 1, 3);
        gridPane.add(dtmfStar, 0, 3);
        gridPane.add(dtmfHash, 2, 3);

        sentTones = new TextField();
        typedTones = new TextField();

        sentTones.setEditable(false);
        sentTones.setPrefWidth(135);
        sentTones.setTooltip(new Tooltip("Sent Tones"));

        typedTones.setPrefWidth(90);
        typedTones.setTextFormatter(new TextFormatter<>(filter));
        typedTones.setTooltip(new Tooltip("Manual Tones to send"));
        typedTones.setOnKeyReleased(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                dtmfButtonClicked(null);
            }
        });
        gridPane.add(sentTones, 0, 4, 3, 1);
        gridPane.add(typedTones, 0, 5, 2, 1);
        gridPane.add(dtmfSend, 2, 5);
        GridPane.setMargin(sentTones, new Insets(5, 0, 5, 0));
    }

    public void dtmfButtonClicked(ActionEvent e) {
        String methodName = "dtmfButtonClicked() ";
        Button selected = null;

        if (interactionId == null) {
            LOG.info(methodName + "No interaction to play DTMF on");
            return;
        }

        if (e != null) {
            selected = (Button) e.getSource();
            LOG.trace(methodName + "keypad pressed = " + selected.getText());
        }

        if (selected == null || selected == dtmfSend) {
            if (!typedTones.getText().isEmpty()) {
                LOG.trace(methodName + "sending digits = " + typedTones.getText());
                String existingText = sentTones.getText();
                existingText += typedTones.getText();
                sentTones.setText(existingText);
                interactionExe.playDTMF(typedTones.getText(), interactionId);
                typedTones.clear();
            }
        } else { // Single digit
            LOG.trace(methodName + "sending digit = " + selected.getText());
            String existingText = sentTones.getText();
            existingText += selected.getText();
            sentTones.setText(existingText);
            interactionExe.playDTMF(selected.getText(), interactionId);
        }
    }
}
