package com.ntels.onecable.admin.common.websocket;

import com.ntels.onecable.admin.common.AppConfig;
import com.ntels.onecable.admin.common.Constants;
import com.ntels.onecable.admin.common.util.Dlog;
import com.ntels.onecable.admin.common.util.LogUtil;
import com.ntels.onecable.admin.common.util.Util;

import org.java_websocket.client.WebSocketClient;
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.onecable.admin.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 WebSocketClient webSocket;
    private Util util;
    private Handler handler;
    private AppConfig mAppConfig;

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

    /**
     * Websocket 인증.
     */
    public void sendClientConnectAuth() {
//        HashMap<String, Object> sendParams = new HashMap<String, Object>();
//        sendParams.put(Constants.KEY_MESSAGE_TYPE, Constants.WEBSOCKET_TYPE_AUTH);
//        sendParams.put(Constants.KEY_MEMBER_ID, mAppConfig.getLoginId());
//        sendParams.put(Constants.KEY_PASSWORD, mAppConfig.getLogin_Pass());
//        sendParams.put(Constants.KEY_OS_TYPE, Constants.OS_TYPE);
//        sendParams.put(Constants.KEY_DEVICE_TOKEN, mAppConfig.getPush_Token());
//        send(mUtil.MapToJson(sendParams));
        HashMap<String, Object> sendParams = new HashMap<>();
        sendParams.put(Constants.KEY_MESSAGE_TYPE, Constants.WEBSOCKET_TYPE_AUTH_AUTO);
        sendParams.put(Constants.KEY_AUTHORIZATION, mAppConfig.getAuthorization());
        sendParams.put(Constants.KEY_OS_TYPE, Constants.OS_TYPE);
        sendParams.put(Constants.KEY_DEVICE_TOKEN, mAppConfig.getPush_Token());
        send(util.MapToJson(sendParams));
    }

    /**
     * 서비스허브에 노드 동기화를 요청한다.(데이터 동기화 아님)
     */
    public void sendWssTest() {

        HashMap<String, Object> sendParams = new HashMap<>();
        sendParams.put(Constants.KEY_MESSAGE_TYPE, Constants.WEBSOCKET_TYPE_AUTH);
        sendParams.put(Constants.KEY_MEMBER_ID, "100");
        sendParams.put(Constants.KEY_MEMBER_PASSWORD, "1234");
        sendParams.put(Constants.KEY_OS_TYPE, Constants.OS_TYPE);
        sendParams.put(Constants.KEY_CUST_ID, "1002");
        sendParams.put(Constants.KEY_CTRT_GRP_ID, "1002");
        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 sendClientAuth(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 일반 로그인
     *
     * @param hmParams Request parameter
     */
    public void sendClient(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 자동 로그인
     *
     * @param hmParams Request parameter
     */
    public void sendClientAuthAuto(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.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.KEY_CMDCLS_ID)),
                        util.null2string(hmParams.get(Constants.KEY_CMDCLS_VALUE)));

                hmParams.remove(Constants.KEY_CMDCLS_ID);
                hmParams.remove(Constants.KEY_CMDCLS_VALUE);

                joSendParams = new JSONObject(util.MapToJson(hmParams));
                joSendParams.put(Constants.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) {
        Dlog.v("sendParams = " + hmParams);
        String commandType = util.null2string(hmParams.get(Constants.KEY_COMMAND_TYPE));
        if (commandType.equals(Constants.WEBSOCKET_COMM_TYPE_CONTROL)||commandType.equals(Constants.WEBSOCKET_COMM_TYPE_UNPAIRING_NODE)) {
            JSONObject joSendParams = null;
            JSONObject joRequestValue = new JSONObject();

            try {
                joRequestValue.put(util.null2string(hmParams.get(Constants.KEY_CMDCLS_ID))
                                 , util.null2string(hmParams.get(Constants.KEY_CMDCLS_VALUE)));

                Dlog.v("joRequestValue = " + joRequestValue);
                hmParams.remove(Constants.KEY_CMDCLS_ID);
                hmParams.remove(Constants.KEY_CMDCLS_VALUE);

                joSendParams = new JSONObject(util.MapToJson(hmParams));
                joSendParams.put(Constants.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));
    }

    /**
     * 노드 프로파일 업데이트 요청.
     *
     * @param hmParams Request parameter
     */
    public void sendFirmwareUpgrade(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }
    /**
     * 노드 프로파일 업데이트 요청.
     *
     * @param hmParams Request parameter
     */
    public void sendSoftwareUpgrade(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }
    /**
     * 노드 프로파일 업데이트 요청.
     *
     * @param hmParams Request parameter
     */
    public void sendNodeProfileUpdate(HashMap<String, Object> hmParams) {
        send(util.MapToJson(hmParams));
    }

    /**
     * 로그아웃.
     *
     * @param hmParams Request parameter
     */
    public void sendAuthOut(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.v(TAG, "webSocket.connect() : " + webSocket.getReadyState());
                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);
    }
}
