package com.tomas.lps_asi.lib;

import android.content.Context;
import android.util.Log;


import com.tomas.lps_asi.R;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

public class TcpClient extends Thread {

    public static Context context;
    public static String SERVER_IP;
    public static int SERVER_PORT;
    // message to send to the server
    private String mServerMessage;
    // sends message received notifications
    private OnMessageReceived mMessageListener = null;
    // while this is true, the server will continue running
    private boolean mRun = false;
    private boolean mSuccess = false;
    // used to send messages
    private PrintWriter mBufferOut;
    // used to read messages from the server
    private BufferedReader mBufferIn;

    private String message;

    /**
     * Constructor of the class. OnMessagedReceived listens for the messages received from server
     */
    public TcpClient(String server_ip, int port, Context context, String message
            , OnMessageReceived listener) {
        SERVER_IP = server_ip;
        SERVER_PORT = port;
        this.context = context;
        this.message = message;
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     *
     * @param message text entered by client
     */
    public void sendMessage(final String message) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if (mBufferOut != null) {
                    Log.d(context.getString(R.string.tag), "Sending: " + message);
                    mBufferOut.println(message);
                    mBufferOut.flush();
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

    /**
     * Close the connection and release the members
     */
    public void stopClient() {

        mRun = false;

        if (mBufferOut != null) {
            mBufferOut.flush();
            mBufferOut.close();
        }

        mMessageListener = null;
        mBufferIn = null;
        mBufferOut = null;
        mServerMessage = null;
    }

    public void run() {

        mRun = true;

        try {
            //here you must put your computer's IP address.
            InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

            Log.d(context.getString(R.string.tag), String.format("C: Connecting to %s:%d...", SERVER_IP, SERVER_PORT));

            //create a socket to make the connection with the server
            //Socket socket = new Socket(serverAddr, SERVER_PORT);
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), 10000 );

            try {

                //sends the message to the server
                mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                if (mBufferOut != null) {
                    Log.d(context.getString(R.string.tag), "Sending: " + message);
                    mBufferOut.println(message);
                    mBufferOut.flush();
                }

                //receives the message which the server sends back
                mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));


                //in this while the client listens for the messages sent by the server
                while (mRun) {

                    mServerMessage = mBufferIn.readLine();

                    if (mServerMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(mServerMessage);
                    }

                }

                Log.d(context.getString(R.string.tag), "S: Received Message: '" + mServerMessage + "'");
                mSuccess = true;

            } catch (Exception e) {
                Log.e(context.getString(R.string.tag), "S: Error", e);
                mMessageListener.messageReceived("ERROR");
            } finally {
                //the socket must be closed. It is not possible to reconnect to this socket
                // after it is closed, which means a new socket instance has to be created.
                socket.close();
            }

        } catch (Exception e) {
            Log.e(context.getString(R.string.tag), "C: Error", e);
            mMessageListener.messageReceived("ERROR");
        }

    }

    //Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
    //class at on AsyncTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }

    public boolean isSuccess() {
        return mSuccess;
    }
}
