package pt.epvc.ambrosioandroid;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.speech.RecognizerIntent;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

public class DetalheBebida extends AppCompatActivity {

    private TextView tv_Speech_to_text;
    private static final int REQUEST_CODE_SPEECH_INPUT = 1;
    private FloatingActionButton ambrosioButton;
    private String nomeBebida;
    private Bebida bebidas [] = new Bebida[8];
    private ImageView imagemBebida;
    private TextView descricaoBebida;
    private TextView nomeBebidaTextView;
    private String comando;
    private BluetoothAdapter mBTAdapter;
    private Set<BluetoothDevice> mPairedDevices;
    private ArrayAdapter<String> mBTArrayAdapter;
    private ListView mDevicesListView;
    private Handler mHandler; // Our main handler that will receive callback notifications
    private ConnectedThread mConnectedThread; // bluetooth background worker thread to send and receive data
    private BluetoothSocket mBTSocket = null; // bi-directional client-to-client data path
    private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
    private final static int MESSAGE_READ = 2; // used in bluetooth handler to identify message update
    private final static int CONNECTING_STATUS = 3; // used in bluetooth handler to identify message status
    private View background;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bebida);

        ambrosioButton = findViewById(R.id.ambrosioButton);

        background = (View) findViewById(R.id.background_dim);
        progressBar = (ProgressBar)findViewById(R.id.progressBar);

        //mBTArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
        mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio

        /*mDevicesListView = (ListView)findViewById(R.id.devicesListView);
        mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
        mDevicesListView.setOnItemClickListener(mDeviceClickListener);*/

        mHandler = new Handler(){
            public void handleMessage(android.os.Message msg){
                if(msg.what == MESSAGE_READ){
                    String readMessage = null;
                    try {
                        readMessage = new String((byte[]) msg.obj, "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    //mReadBuffer.setText(readMessage);
                }

                if(msg.what == CONNECTING_STATUS){
                    if(msg.arg1 == 1) {
                        progressBar.setVisibility(View.INVISIBLE);
                        background.setVisibility(View.INVISIBLE);
                        //Toast.makeText(Bebida.this, "Connected to Device: " + (String)(msg.obj), Toast.LENGTH_SHORT).show();
                        //mBluetoothStatus.setText("Connected to Device: " + (String)(msg.obj));
                    }
                    else {
                        progressBar.setVisibility(View.INVISIBLE);
                        background.setVisibility(View.INVISIBLE);
                        Toast.makeText(DetalheBebida.this, "Conexão falhou", Toast.LENGTH_SHORT).show();
                        //mBluetoothStatus.setText("Connection Failed");
                    }
                }
            }
        };

        ligarBluetooth();
        /*if (mBTArrayAdapter == null) {
            // Device does not support Bluetooth
            //mBluetoothStatus.setText("Status: Bluetooth not found");
            Toast.makeText(Bebida.this,"Bluetooth device not found!",Toast.LENGTH_SHORT).show();
        }
        else{
            ligarBluetooth();
        }*/

        nomeBebida = getIntent().getExtras().getString("nomeBebida");

        FloatingActionButton floatingActionButton = (FloatingActionButton)findViewById(R.id.floatingActionButton);

        ambrosioButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent intent
                        = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                        RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,
                        Locale.getDefault());
                intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speak to text");

                try {
                    startActivityForResult(intent, REQUEST_CODE_SPEECH_INPUT);
                }
                catch (Exception e) {
                    Toast
                            .makeText(DetalheBebida.this, " " + e.getMessage(),
                                    Toast.LENGTH_SHORT)
                            .show();
                }

            }
        });

        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                switch (nomeBebida){
                    case "Cosmopolitan": comando = "1";break;
                    case "Tropical": comando = "2";break;
                    case "Cinderela": comando = "3";break;
                    case "San Francisco": comando = "4";break;
                    case "Ugly Kid": comando = "5";break;
                    case "Bela Ragazza": comando = "6";break;
                    case "Tango": comando = "7";break;
                    case "Pneu": comando = "8";break;
                }
                Toast.makeText(DetalheBebida.this, "A sair " + nomeBebida, Toast.LENGTH_SHORT).show();
                try {
                    mConnectedThread.enviarComando(comando);
                }
                catch (Exception e){
                    Toast.makeText(DetalheBebida.this, "Ligue a máquina", Toast.LENGTH_SHORT).show();
                }
            }
        });

        bebidas[0] = new Bebida();
        bebidas[0].setNomeBebida("Cosmopolitan");
        bebidas[0].setDescricaoBebida("Ingredientes:\n" +
                " - Groselha\n" +
                " - Sumo de Limão\n" +
                " - Sumo de Laranja\n" +
                " - Água de Côco\n\n");
        bebidas[0].setImagemBebida(R.drawable.cosmopolitan);

        bebidas[1] = new Bebida();
        bebidas[1].setNomeBebida("Tropical");
        bebidas[1].setDescricaoBebida("Ingredientes:\n" +
                " - Sumo de Limão\n" +
                " - Sumo de Laranja\n" +
                " - Água com Gás\n\n");
        bebidas[1].setImagemBebida(R.drawable.tropical);

        bebidas[2] = new Bebida();
        bebidas[2].setNomeBebida("Cinderela");
        bebidas[2].setDescricaoBebida("Ingredientes:\n" +
                " - Sumo de Limão\n" +
                " - Sumo de Laranja\n" +
                " - Sumo de Ananás\n\n");
        bebidas[2].setImagemBebida(R.drawable.cinderela);

        bebidas[3] = new Bebida();
        bebidas[3].setNomeBebida("San Francisco");
        bebidas[3].setDescricaoBebida("Ingredientes:\n" +
                " - Sumo de Limão\n" +
                " - Sumo de Ananás\n" +
                " - Sumo de Laranja\n" +
                " - Sumo de Pêra\n\n");
        bebidas[3].setImagemBebida(R.drawable.sanfrancisco);

        bebidas[4] = new Bebida();
        bebidas[4].setNomeBebida("Ugly Kid");
        bebidas[4].setDescricaoBebida("Ingredientes:\n" +
                " - Sumo de Laranja\n" +
                " - Sumo de Limão\n" +
                " - Groselha\n\n");
        bebidas[4].setImagemBebida(R.drawable.ugly);

        bebidas[5] = new Bebida();
        bebidas[5].setNomeBebida("Bela Ragazza");
        bebidas[5].setDescricaoBebida("Ingredientes:\n" +
                " - Sumo de Limão\n" +
                " - Café\n" +
                " - Coca-Cola\n\n");
        bebidas[5].setImagemBebida(R.drawable.ragazza);

        bebidas[6] = new Bebida();
        bebidas[6].setNomeBebida("Tango");
        bebidas[6].setDescricaoBebida("Ingredientes:\n" +
                " - 7 Up\n" +
                " - Groselha\n\n");
        bebidas[6].setImagemBebida(R.drawable.tango);

        bebidas[7] = new Bebida();
        bebidas[7].setNomeBebida("Pneu");
        bebidas[7].setDescricaoBebida("Ingredientes:\n" +
                " - Água com Gás\n" +
                " - Sumo de Limão\n\n");
        bebidas[7].setImagemBebida(R.drawable.pneu);

        imagemBebida = (ImageView)findViewById(R.id.imagemBebida);
        descricaoBebida = (TextView)findViewById(R.id.descricaoBebida);
        nomeBebidaTextView = (TextView)findViewById(R.id.nomeBebida);


        //Toast.makeText(this, nomeBebida,Toast.LENGTH_SHORT).show();

        for (Bebida bebida : bebidas){
            if (bebida.getNomeBebida().equals(nomeBebida)){
                descricaoBebida.setText(bebida.getDescricaoBebida());
                imagemBebida.setImageResource(bebida.getImagemBebida());
                nomeBebidaTextView.setText(bebida.getNomeBebida());
            }
        }

    }
    public void ligarBluetooth(){
        mBTAdapter = BluetoothAdapter.getDefaultAdapter();
        if (!mBTAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            //mBluetoothStatus.setText("Bluetooth enabled");
            Toast.makeText(DetalheBebida.this,"Bluetooth turned on",Toast.LENGTH_SHORT).show();

        }
        else{
            Toast.makeText(DetalheBebida.this,"Bluetooth is already on", Toast.LENGTH_SHORT).show();
        }
        //listarAparelhos();
        if(!mBTAdapter.isEnabled()) {
            Toast.makeText(getBaseContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
            return;
        }
        progressBar.setVisibility(View.VISIBLE);
        background.setVisibility(View.VISIBLE);
        Toast.makeText(DetalheBebida.this, "A conectar...", Toast.LENGTH_SHORT).show();
        //mBluetoothStatus.setText("Connecting...");
        // Get the device MAC address, which is the last 17 chars in the View
        //String info = ((TextView) v).getText().toString();
        final String address = "98:D3:61:FD:4B:D6";
        final String name = "HC-05";

        // Spawn a new thread to avoid blocking the GUI one
        new Thread()
        {
            public void run() {
                boolean fail = false;

                BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
                Log.d("teste","tentou ligar");
                try {
                    mBTSocket = createBluetoothSocket(device);
                    Log.d("teste","criou socket");
                } catch (IOException e) {
                    fail = true;
                    Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
                }
                // Establish the Bluetooth socket connection.
                try {
                    Log.d("teste","tentou conectar ao socket");
                    mBTSocket.connect();
                    Log.d("teste","ligou ao socket");
                } catch (IOException e) {
                    try {
                        fail = true;
                        mBTSocket.close();
                        mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
                                .sendToTarget();
                    } catch (IOException e2) {
                        //insert code to deal with this
                        Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
                    }
                }
                if(fail == false) {
                    mConnectedThread = new ConnectedThread(mBTSocket);
                    mConnectedThread.start();

                    mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
                            .sendToTarget();
                }
            }
        }.start();
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        // Check which request we're responding to
        if (requestCode == REQUEST_CODE_SPEECH_INPUT) {
            if (resultCode == RESULT_OK && data != null) {
                ArrayList<String> result = data.getStringArrayListExtra(
                        RecognizerIntent.EXTRA_RESULTS);
                String bebida = "";
                if(Objects.requireNonNull(result).get(0).toLowerCase().contains("ambrósio")){
                    if (Objects.requireNonNull(result).get(0).toLowerCase().contains("cosmopolitan")){
                        comando = "1";
                        bebida = "Cosmopolitan";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("cosmopolitan")){
                        comando = "1";
                        bebida = "Cosmopolitan";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("tropical")){
                        comando = "2";
                        bebida = "Tropical";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("cinderela")){
                        comando = "3";
                        bebida = "Cinderela";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("são francisco")){
                        comando = "4";
                        bebida = "San Francisco";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("ugly kid")){
                        comando = "5";
                        bebida = "Ugly Kid";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("bela ragazza")){
                        comando = "6";
                        bebida = "Bela Ragazza";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("tango")){
                        comando = "7";
                        bebida = "Tango";
                    }
                    else if (Objects.requireNonNull(result).get(0).toLowerCase().contains("pneu")){
                        comando = "8";
                        bebida = "Pneu";
                    }
                    Toast.makeText(this, "A tirar um " + bebida, Toast.LENGTH_SHORT).show();
                    //mConnectedThread.enviarComando(comando);
                }
            }
        }
        if (requestCode == REQUEST_ENABLE_BT) {
            // Make sure the request was successful
            if (resultCode == RESULT_OK) {
                // The user picked a contact.
                // The Intent's data Uri identifies which contact was selected.
                //mBluetoothStatus.setText("Enabled");
                Toast.makeText(this, "Enabled", Toast.LENGTH_SHORT).show();
            }
            else
                Toast.makeText(this, "Disabled", Toast.LENGTH_SHORT).show();
            //mBluetoothStatus.setText("Disabled");
        }
    }
    /*public void listarAparelhos(){
        mPairedDevices = mBTAdapter.getBondedDevices();
        if(mBTAdapter.isEnabled()) {
            // put it's one to the adapter
            for (BluetoothDevice device : mPairedDevices)
                mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());

            Toast.makeText(getApplicationContext(), "Show Paired Devices", Toast.LENGTH_SHORT).show();
        }
        else
            Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
    }*/


    private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {


        }
    };
    private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
        return  device.createRfcommSocketToServiceRecord(BTMODULEUUID);
        //creates secure outgoing connection with BT device using UUID
    }
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            byte[] buffer = new byte[1024];  // buffer store for the stream
            int bytes; // bytes returned from read()
            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.available();
                    if (bytes != 0) {
                        SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
                        bytes = mmInStream.available(); // how many bytes are ready to be read?
                        bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
                        mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                                .sendToTarget(); // Send the obtained bytes to the UI activity
                    }
                } catch (IOException e) {
                    e.printStackTrace();

                    break;
                }
            }
        }
        public void enviarComando(String input){
            byte[] bytes = input.getBytes();           //converts entered String into bytes
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) { }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            mBTSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
