package org.agentspace.recognize4pc;

import android.speech.RecognizerIntent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import java.util.ArrayList;
import java.util.List;

public class VoiceRecognitionActivity extends AppCompatActivity {

    private Button mbtSpeak;
    private Button mbtConnect;
    private TextView mtRecognized;
    private EditText metIP;

    public static Socket socket = null;
    public static String recognized = "";
    public static int serverPort = 7171;
    public static String serverIP = "192.168.1.13";

    private static final int VOICE_RECOGNITION_REQUEST_CODE = 1001;

    public void checkVoiceRecognition() {
        // Check if voice recognition is present
        PackageManager pm = getPackageManager();
        List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(
                RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
        if (activities.size() == 0) {
            mbtSpeak.setEnabled(false);
            Toast.makeText(this, "Voice recognizer not present",
                    Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_voice_recognition);
        mbtSpeak = (Button) findViewById(R.id.btSpeak);
        mbtConnect = (Button) findViewById(R.id.btConnect);
        mtRecognized = (TextView) findViewById(R.id.tRecognized);
        metIP = (EditText) findViewById(R.id.etIP);
        mbtSpeak.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                // Specify the calling package to identify your application
                intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass().getPackage().getName());

                // Display an hint to the user about what he should say.
                //intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "");

                // Given an hint to the recognizer about what the user is going to say
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);

                // Stop recording ASAP
                intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 1500);

                int noOfMatches = 1;
                // Specify how many results you want to receive. The results will be
                // sorted where the first result is the one with higher confidence.

                intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, noOfMatches);

                startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);

                //showToastMessage("called ok");
            }
        });
        mbtConnect.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String serverDescription = metIP.getText().toString();
                int ind = serverDescription.indexOf(':');
                if (ind != -1) {
                    serverIP = serverDescription.substring(0,ind);
                    serverPort = Integer.parseInt(serverDescription.substring(ind+1));
                }
                else {
                    serverIP = serverDescription;
                    serverPort=7171;
                }
                showToastMessage("connecting "+serverIP+":"+serverPort);
                new Thread(new ConnectThread()).start();
            }
        });
        checkVoiceRecognition();
/*        new Thread(){
            public void run() {
                for (;;) {
                    if (out == null || out.checkError()) {
                        try {
                            serverIP = metIP.getText().toString();
                            showToastMessage("connecting to "+serverIP);
                            InetAddress serverAddr = InetAddress.getByName(serverIP);
                            socket = new Socket(serverAddr, serverPort);
                            out = new PrintWriter(socket.getOutputStream(), true);
                            //showToastMessage("connected to "+serverIP);
                            out.println("connect");
                        } catch (Exception ee) {
                            out = null;
                            //showToastMessage("failed "+serverIP);
                            //ee.printStackTrace();
                        }
                    }
                    try {
                        sleep(1000);
                    } catch (InterruptedException ee) {
                    }
                }
            }
        }.start();
*/
    }

    private void sendRecognizedText (String str) {
        recognized = str;
        new Thread(new SendingThread()).start();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == VOICE_RECOGNITION_REQUEST_CODE) {

            //If Voice recognition is successful then it returns RESULT_OK
            if (resultCode == RESULT_OK) {

                ArrayList<String> textMatchList = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                if (!textMatchList.isEmpty()) {
                    // populate the Matches
                    showToastMessage("OK "+textMatchList.get(0));
                    mtRecognized.setText(textMatchList.get(0));
                    sendRecognizedText(textMatchList.get(0));
                    //mbtSpeak.performClick();
                }
                else {
                    showToastMessage("OK "+textMatchList.size());
                }

            //Result code for various error.
            } else if (resultCode == RecognizerIntent.RESULT_AUDIO_ERROR) {
                showToastMessage("Audio Error");
            } else if (resultCode == RecognizerIntent.RESULT_CLIENT_ERROR) {
                showToastMessage("Client Error");
            } else if (resultCode == RecognizerIntent.RESULT_NETWORK_ERROR) {
                showToastMessage("Network Error");
            } else if (resultCode == RecognizerIntent.RESULT_NO_MATCH) {
                showToastMessage("No Match");
            } else if (resultCode == RecognizerIntent.RESULT_SERVER_ERROR) {
                showToastMessage("Server Error");
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    void showToastMessage(String message){
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }

    class ConnectThread implements Runnable {

        @Override
        public void run() {
            try {
                //showToastMessage("connecting to "+serverIP);
                InetAddress serverAddr = InetAddress.getByName(serverIP);
                socket = new Socket(serverAddr, serverPort);
                //out = new PrintWriter(socket.getOutputStream(), true);
                PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
                //showToastMessage("connected to "+serverIP+":"+serverPort);
                out.println("connect");
            } catch (Exception ee) {
                socket = null;
                //showToastMessage("connection failed "+ee);
            }
        }

    }

    class SendingThread implements Runnable {

        @Override
        public void run() {
            if (socket == null) return;
            try {
                PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                out.println(recognized);
                //showToastMessage("sending " + recognized);
                recognized = "";
            } catch (Exception ee) {
                //showToastMessage("sending failed " + ee);
            }
        }

    }
}



