package com.tomas.ckd_system;

import static com.tomas.ckd_system.WsProtocol.COMMAND.RESET_REQUEST;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.tomas.ckd_system.lib.Device_HT;
import com.tomas.ckd_system.lib.SpinAdapterDevice;
import com.tomas.ckd_system.lib.Settings;
import com.tomas.ckd_system.lib.SpinAdapterUser;
import com.tomas.ckd_system.lib.User;
import com.tomas.ckd_system.lib.common.AsyncHttpClient;
import com.tomas.ckd_system.lib.common.CallbackListener;
import com.tomas.ckd_system.lib.common.MessageListener;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

import cn.pedant.SweetAlert.SweetAlertDialog;
import okhttp3.WebSocket;

public class Login_Activity extends AppCompatActivity implements View.OnClickListener, CallbackListener, MessageListener {
    TextView txt_user, lbl_main_title;
    EditText edt_password;
    Spinner spinner_ht;
    Button btn_login;
    Dialog dialog;
    SpinAdapterUser spinAdapterUser;
    SpinAdapterDevice spinAdapterDevice;
    ArrayList<String> user_list;
    private static int title_click = 0;
    WsClient wsClient;

    HashMap<String, Device_HT> Device_connect;

    int position_id;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        user_list = new ArrayList<String>();
        Device_connect = new LinkedHashMap<String,Device_HT>();

        edt_password = (EditText) findViewById(R.id.edt_password);
        lbl_main_title = (TextView) findViewById(R.id.lbl_main_title);
        spinner_ht = (Spinner) findViewById(R.id.spinner_ht);
        btn_login = (Button) findViewById(R.id.btn_login);

        txt_user = (TextView)findViewById(R.id.txt_user);
        txt_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Alert_Search();

            }
        });

        // read settings from Internal storage
        Settings.init(Login_Activity.this);
        Settings.setLine_no("");

        init();
        Connect_WS();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_login:
                //Set device connect HT

//                FOR TEST
//                if (txt_user.getText().toString().equals("admin")){
//
//                    Settings.setLoginUser((User) spinAdapterUser.findItem("admin"));
//                    Settings.setDeviceNo("10");
//                    Settings.setArea_stage("staging");
//
//                    Intent intent1 = new Intent(Login_Activity.this, MainActivity.class);
//                    startActivity(intent1);
//                }

                if (txt_user.getText().toString().trim().equals("")||edt_password.getText().toString().trim().equals(""))
                    return;

                if(Device_connect.size() == 0){
                    new SweetAlertDialog(Login_Activity.this, SweetAlertDialog.WARNING_TYPE)
                            .setTitleText("WARNING")
                            .setContentText("Paired handy device's not found.")
                            .show();

                }else{

                    String user_id = txt_user.getText().toString().trim();
                    Log.d(getString(R.string.tag), user_id);

                    if (!edt_password.getText().toString().equals(
                            ((User) spinAdapterUser.findItem(user_id)).getPassword())) {
                        Toast.makeText(getApplicationContext(), "Password wrong!", Toast.LENGTH_LONG).show();
                        return;
                    }

                    //Set user login
                    Settings.setLoginUser((User) spinAdapterUser.findItem(user_id));
                    //Set device connect HT
                    Settings.setDeviceHT((Device_HT) spinAdapterDevice.getItem(spinner_ht.getSelectedItemPosition()));

                    //sent data to ws
                    try {
                        JSONObject j_ext;
                        j_ext = new JSONObject();
                        j_ext.put("device_id", Settings.getDeviceNo());
                        j_ext.put("user_id", Settings.getLoginUser().getId());
                        j_ext.put("device_type", getString(R.string.device_type));
                        j_ext.put("pair_id", Settings.getDeviceHT().getDevice_id());
                        j_ext.put("pair_dev_type",getString(R.string.pair_dev_type));
                        WsClient.getInstance().sendMessage(
                                WsProtocol.encapsulation(
                                        WsProtocol.COMMAND.REGISTER_REQUEST.toString(),
                                        j_ext
                                )
                        );

                    } catch (JSONException e) {
                        new SweetAlertDialog(Login_Activity.this, SweetAlertDialog.ERROR_TYPE)
                                .setTitleText("ERROR")
                                .setContentText(e.getMessage())
                                .show();
                    } catch (Exception e) {
                        if (e.getMessage().trim().equals("The server might crash")){
                            WsClient.getInstance().connect();
                        }
                    }
                }
                break;

            case R.id.lbl_main_title:
                if (++title_click == 7) {
                    title_click = 0;
                    Toast.makeText(getApplicationContext(), "Settings mode!", Toast.LENGTH_LONG).show();

                    // call Settings activity
                    Log.d(getString(R.string.tag), "start settings activity");
                    Intent intent = new Intent(Login_Activity.this, SettingActivity.class);
                    startActivity(intent);

                    txt_user.setText("");
                    edt_password.setText("");

                }
        }
    }

    private void Connect_WS() {
        if (Settings.getMgmtList().containsKey("ws_node")){
            wsClient = WsClient.getInstance(
                     this,
                    this,
                    getApplicationContext(),
                    Settings.getMgmtList().get("ws_node")
            );
        }
    }


    @Override
    public void onMessage(WebSocket webSocket, String text) {
        Log.d(getString(R.string.tag), String.format("%s : received -> \"%s\"", this.getLocalClassName(),
                text));
        runOnUiThread(new Runnable() {
            @Override
            public void run() {

                try {
                    JSONObject jsonObject = new JSONObject(text);
                    JSONObject j_ext;

                    switch (WsProtocol.COMMAND.valueOf(jsonObject.getString("cmd"))) {

                        case HELLO:
                            Log.d(getString(R.string.tag), "cmd : HELLO");

                            j_ext = new JSONObject(jsonObject.getString("ext"));
                            WsClient.getInstance().client_id = j_ext.getInt("id");

                            j_ext = new JSONObject();
                            j_ext.put("device_id", Settings.getDeviceNo());
                            j_ext.put("user_id", "");
                            j_ext.put("device_type",getString(R.string.device_type));
                            j_ext.put("list_type", getString(R.string.pair_dev_type));
                            WsClient.getInstance().sendMessage(
                                    WsProtocol.encapsulation(
                                            WsProtocol.COMMAND.GET_DEVICE_LIST_REQUEST.toString(),
                                            j_ext
                                    )
                            );
                            break;

                        case GET_DEVICE_LIST_ACK:

                            Log.d(getString(R.string.tag), "cmd : GET_DEVICE_LIST_ACK");

                            JSONArray json_Array = new JSONArray(jsonObject.getString("ext"));
                            for (int i = 0; i < json_Array.length(); i++) {
                                String device_id = json_Array.getJSONObject(i).getString("device_id");
                                String device_type = json_Array.getJSONObject(i).getString("device_type");
                                String user_id = json_Array.getJSONObject(i).getString("user_id");
                                String area_con = json_Array.getJSONObject(i).getString("area");
                                String status = json_Array.getJSONObject(i).getString("status");

                                Device_connect.put(device_id, new Device_HT(device_id, device_type, user_id, area_con, status));

                            }
                            List<Device_HT> devices = new ArrayList<>();
                            for (String key : Device_connect.keySet()){
                                devices.add( Device_connect.get(key));
                            }


                            spinAdapterDevice = new SpinAdapterDevice(
                                    getApplicationContext(), R.layout.spinner_usr_list, devices.toArray(new Device_HT[devices.size()]));
                            spinner_ht.setAdapter(spinAdapterDevice);
                            break;

                        case REGISTER_ACK:
                            Log.d(getString(R.string.tag), "cmd : REGISTER_ACK");
                            j_ext = new JSONObject(jsonObject.getString("ext"));
                            String area =  j_ext.getString("area");

                            //set area
                            Settings.setArea_stage(area);

                            Intent intent1 = new Intent(Login_Activity.this, MainActivity.class);
                            startActivity(intent1);

                            txt_user.setText("");
                            edt_password.setText("");

                            break;

                        case DEVICE_CONNECT_NOTIFY_REQUEST:
                            Log.d(getString(R.string.tag), "cmd : DEVICE_CONNECT_NOTIFY_REQUEST");

                            j_ext = new JSONObject(jsonObject.getString("ext"));
                            String device_id = j_ext.getString("device_id");
                            String device_type = j_ext.getString("device_type");
                            String user_id = j_ext.getString("user_id");
                            String area1 = j_ext.getString("area");
                            String status = j_ext.getString("status");

                            if (!Device_connect.containsKey(device_id)){

                                Device_connect.put(device_id, new Device_HT(device_id, device_type, user_id, area1, status));

                                List<Device_HT> devices1 = new ArrayList<>();
                                for (String key : Device_connect.keySet()){
                                    devices1.add( Device_connect.get(key));
                                }

                                spinAdapterDevice = new SpinAdapterDevice(
                                        getApplicationContext(), R.layout.spinner_usr_list, devices1.toArray(new Device_HT[devices1.size()]));
                                spinner_ht.setAdapter(spinAdapterDevice);

                            }
                            WsClient.getInstance().sendMessage(
                                    WsProtocol.encapsulation(
                                            WsProtocol.COMMAND.DEVICE_CONNECT_NOTIFY_ACK.toString(),
                                            null
                                    )
                            );
                            break;

                        case DEVICE_DISCONNECT_NOTIFY_REQUEST:
                            Log.d(getString(R.string.tag), "cmd : DEVICE_DISCONNECT_NOTIFY_REQUEST");

                            j_ext = new JSONObject(jsonObject.getString("ext"));
                            String device_id1 = j_ext.getString("device_id");

                            if (Device_connect.containsKey(device_id1)){

                                Device_connect.remove(device_id1);

                                List<Device_HT> devices_dis = new ArrayList<>();
                                for (String key : Device_connect.keySet()){
                                    devices_dis.add( Device_connect.get(key));
                                }

                                spinAdapterDevice = new SpinAdapterDevice(
                                        getApplicationContext(), R.layout.spinner_usr_list, devices_dis.toArray(new Device_HT[devices_dis.size()]));
                                spinner_ht.setAdapter(spinAdapterDevice);

                            }
                            WsClient.getInstance().sendMessage(
                                    WsProtocol.encapsulation(
                                            WsProtocol.COMMAND.DEVICE_DISCONNECT_NOTIFY_ACK.toString(),
                                            null
                                    )
                            );
                            break;

                        case RESET_ACK:

                            break;
                    }
                } catch (JSONException e) {
                    new SweetAlertDialog(Login_Activity.this, SweetAlertDialog.ERROR_TYPE)
                            .setTitleText("ERROR")
                            .setContentText(e.getMessage())
                            .show();
                } catch (Exception e) {
                    if (e.getMessage().trim().equals("The server might crash")){
                        WsClient.getInstance().connect();
                    }
                }
            }
        });
    }

    private void init() {
        user_list.clear();

        // download user data from web
        try {
            JSONObject json = new JSONObject();
            json.put("cmd", "search");
            new AsyncHttpClient(getApplicationContext()
                    ,Settings.getMgmtList().get("web_api") + "/users.php"
                    , json.toString()
            ) {
                @Override
                public void onFinished(String response, int resp_code) {
                    Log.d(getString(R.string.tag), "response: " + response);
                    // update mapItems
                    try {
                        JSONArray jArray = new JSONArray(response);
                        Log.d(getString(R.string.tag), "response json length: " + jArray.length());
                        if (jArray.length() == 0)
                            return;

                        User[] users = new User[jArray.length()];
                        for (int i=0;i<jArray.length();i++) {
                            Log.d(getString(R.string.tag), String.valueOf(i));
                            String id = jArray.getJSONObject(i).getString("id");
                            Log.d(getString(R.string.tag), id);
                            String name = jArray.getJSONObject(i).getString("name");
                            String dept = jArray.getJSONObject(i).getString("dept_id");
                            String role = jArray.getJSONObject(i).getString("auth_id");
                            String password = jArray.getJSONObject(i).getString("password");
                            String status = jArray.getJSONObject(i).getString("status");

                            Log.d(getString(R.string.tag), id + " " + name);
                            users[i] = new User(id, name, password, dept, role, status);

                            user_list.add(id);
                        }

                        Log.d(getString(R.string.tag), Arrays.deepToString(users));

                        spinAdapterUser = new SpinAdapterUser(
                                getApplicationContext(), R.layout.spinner_usr_list, users);
//                        spinAdapterUser = new SpinAdapterUser(
//                                getApplicationContext(), R.layout.spinner_usr_list, users);

                    } catch (JSONException e) {
                        new SweetAlertDialog(Login_Activity.this, SweetAlertDialog.ERROR_TYPE)
                                .setTitleText("ERROR")
                                .setContentText(e.getMessage()+":"+resp_code)
                                .show();
                    }
                }
            }
                    .execute();
        } catch (JSONException e) {
            new SweetAlertDialog(Login_Activity.this, SweetAlertDialog.ERROR_TYPE)
                    .setTitleText("ERROR")
                    .setContentText(e.getMessage())
                    .show();
        }
    }

    private void Alert_Search() {
        // Initialize dialog
        dialog=new Dialog(Login_Activity.this);
        dialog.setContentView(R.layout.dialog_searchable_spinner);
        dialog.getWindow().setLayout(800,900);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        dialog.show();
        // Initialize and assign variable
        EditText editText=dialog.findViewById(R.id.edit_text);
        ListView listView=dialog.findViewById(R.id.list_view);

        // Initialize array adapter
        ArrayAdapter<String> adapter=new ArrayAdapter<>
                (Login_Activity.this, android.R.layout.simple_list_item_1,user_list);

        // set adapter
        listView.setAdapter(adapter);
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                adapter.getFilter().filter(s);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String user_id = adapter.getItem(position);
                position_id = position;
                txt_user.setText(user_id);
                dialog.dismiss();


            }
        });
    }

    @Override
    public void onFinished(String result) {

    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(getString(R.string.tag), "onResume() on class " + getLocalClassName());

        if (Settings.getLoginUser()==null) return;

        // update MessageListener class
        WsClient client = WsClient.getInstance();
        if (client != null) {
            client.setOnMessageListener(this);

            if (!client.isConnected()) {
                // Connect to web socket server
                if (Settings.getMgmtList().containsKey("ws_node")
                        && Settings.getLoginUser()!=null) {
                    wsClient = WsClient.getInstance(
                            Login_Activity.this
                            , Login_Activity.this
                            , getApplicationContext()
                            , Settings.getMgmtList().get("ws_node"));
                }
            }

            try {
                JSONObject j_ext = new JSONObject();
                j_ext.put("device_id", Settings.getDeviceNo());
                j_ext.put("user_id", Settings.getLoginUser().getId());
                j_ext.put("device_type", getString(R.string.device_type));
                j_ext.put("pair_id", Settings.getDeviceHT().getDevice_id());
                j_ext.put("pair_dev_type",getString(R.string.pair_dev_type));
                WsClient.getInstance().sendMessage(
                        WsProtocol.encapsulation(
                                RESET_REQUEST.toString(),
                                j_ext
                        )
                );
            } catch (Exception e) {
                if (e.getMessage().trim().equals("The server might crash")){
                    WsClient.getInstance().connect();
                }
            }
        } else {
            // Connect to web socket server
            if (Settings.getMgmtList().containsKey("ws_node")
                    && Settings.getLoginUser()!=null) {
                wsClient = WsClient.getInstance(
                        Login_Activity.this
                        , Login_Activity.this
                        , getApplicationContext()
                        , Settings.getMgmtList().get("ws_node"));
            }
        }
    }
}