package com.ntels.kneet.v3.common.websocket;

import com.koushikdutta.async.http.WebSocket;
import com.ntels.kneet.v3.common.AppConfig;
import com.ntels.kneet.v3.common.Constants;
import com.ntels.kneet.v3.common.util.LogUtil;
import com.ntels.kneet.v3.common.util.Util;

import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;
import android.os.Handler;

import java.util.HashMap;

/**
 * <pre>
 * 1. ClassName :   WebSocketSender
 * 2. FileName  :   WebSocketSender.java
 * 3. Package   :   com.ntels.kneet.v3.common.websocket
 * 4. Date      :   2016-12-06
 * 5. Author    :   aaron
 * 6. Comment   :   Websocket request class
 * </pre>
 */
public class WebSocketSender {

    private static final String TAG = WebSocketSender.class.getSimpleName();
    private WebSocket webSocket;
    private Util util;
    private Handler handler;
    private AppConfig appConfig;

    /**
     * 생성자.
     *
     * @param webSocket {@link WebSocket}
     * @param handler   Callback event handler
     */
    public WebSocketSender(WebSocket webSocket, Handler handler) {
        this.webSocket = webSocket;
        this.handler = handler;
        this.util = new Util();
        appConfig = AppConfig.getGlobalApplicationContext();
    }

    /**
     * Websocket 인증.
     */
    public void sendClientAuth() {
        HashMap<String, Object> sendParams = new HashMap<String, Object>();
        sendParams.put(Constants.WEBSOCKET_KEY_MESSAGE_TYPE, Constants.WEBSOCKET_TYPE_AUTH);
        sendParams.put(Constants.WEBSOCKET_KEY_MEMBER_ID, appConfig.getLogin_Member_Id());
        sendParams.put(Constants.WEBSOCKET_KEY_AUTH_TOKEN, appConfig.getAuth_Token());
        send(util.MapToJson(sendParams));
    }

    /**
     * 홈허브 등록.
     *
     * @param hmParams Request parameter
     */
    public void sendDeviceRegister(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 홈허브 삭제.
     *
     * @param hmParams Request parameter
     */
    public void sendDeviceDelete(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 노드 제어 명령 요청.
     *
     * @param hmParams Request parameter
     */
    public void sendNodeCommand(HashMap<String, Object> hmParams) {
        String sCommandType = util.null2string(hmParams.get(Constants.WEBSOCKET_KEY_COMMAND_TYPE));
        if (sCommandType.equals(Constants.WEBSOCKET_COMM_TYPE_CONTROL)) {
            JSONObject joSendParams = null;
            JSONObject joRequestValue = new JSONObject();

            try {
                joRequestValue.put(util.null2string(hmParams.get(Constants.WEBSOCKET_KEY_CMDCLS_ID)),
                        util.null2string(hmParams.get(Constants.WEBSOCKET_KEY_CMDCLS_VALUE)));

                hmParams.remove(Constants.WEBSOCKET_KEY_CMDCLS_ID);
                hmParams.remove(Constants.WEBSOCKET_KEY_CMDCLS_VALUE);

                joSendParams = new JSONObject(util.MapToJson(hmParams));
                joSendParams.put(Constants.WEBSOCKET_KEY_REQUEST_VALUE, joRequestValue);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            send(joSendParams.toString());
        } else {
            send(util.MapToJson(hmParams));
        }
    }

    /**
     * 홈허브 제어 명령 요청.
     *
     * @param hmParams Request parameter
     */
    public void sendDeviceCommand(HashMap<String, Object> hmParams) {
        String sCommandType = util.null2string(hmParams.get(Constants.WEBSOCKET_KEY_COMMAND_TYPE));
        if (sCommandType.equals(Constants.WEBSOCKET_COMM_TYPE_CONTROL)) {
            JSONObject joSendParams = null;
            JSONObject joRequestValue = new JSONObject();

            try {
                joRequestValue.put(util.null2string(hmParams.get(Constants.WEBSOCKET_KEY_CMDCLS_ID)),
                        util.null2string(hmParams.get(Constants.WEBSOCKET_KEY_CMDCLS_VALUE)));

                hmParams.remove(Constants.WEBSOCKET_KEY_CMDCLS_ID);
                hmParams.remove(Constants.WEBSOCKET_KEY_CMDCLS_VALUE);

                joSendParams = new JSONObject(util.MapToJson(hmParams));
                joSendParams.put(Constants.WEBSOCKET_KEY_REQUEST_VALUE, joRequestValue);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            send(joSendParams.toString());
        } else {
            send(util.MapToJson(hmParams));
        }
    }

    /**
     * 노드 재 동기화.
     *
     * @param hmParams Request parameter
     */
    public void sendNodeReload(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 노드 등록.
     *
     * @param hmParams Request parameter
     */
    public void sendNodeRegister(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 노드 삭제.
     *
     * @param hmParams Request parameter
     */
    public void sendNodeDelete(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 디바이스 Alive 상태 확인 요청.
     *
     * @param hmParams Request parameter
     */
    public void sendDeviceAlive(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * Websocket request send.
     *
     * @param sParam Request string
     */
    private void send(final String sParam) {
        LogUtil.i(TAG, "send parameter : " + sParam);
        AsyncTask<String, Integer, Boolean> sendTask = new AsyncTask<String, Integer, Boolean>() {

            /**
             * Override this method to perform a computation on a background thread. The
             * specified parameters are the parameters passed to {@link #execute}
             * by the caller of this task.
             * <p/>
             * This method can call {@link #publishProgress} to publish updates
             * on the UI thread.
             *
             * @param params The parameters of the task.
             * @return A result, defined by the subclass of this task.
             * @see #onPreExecute()
             * @see #onPostExecute
             * @see #publishProgress
             */
            @Override
            protected Boolean doInBackground(String... params) {
                LogUtil.i(TAG, "doInBackground");
                LogUtil.i(TAG, "webSocket.isOpen : " + webSocket.isOpen());
                webSocket.send(sParam);
                return true;
            }

            @Override
            protected void onCancelled(Boolean aBoolean) {
                LogUtil.i(TAG, "onCancelled : " + aBoolean);
                handler.sendEmptyMessage(WebSocketService.WEBSOCKET_CONNECT_TIMEOUT);
            }
        };
        new AsyncTaskCancelTimerTask(sendTask, 20000, 1000, true).start();
        sendTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
}
