package com.tomastc.anickd;

import android.content.Intent;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.keyence.autoid.sdk.scan.DecodeResult;
import com.tomastc.anickd.BuildConfig;
import com.tomastc.anickd.lib.KeyMapping;
import com.tomastc.anickd.lib.Scanner;
import com.tomastc.anickd.lib.Settings;
import com.tomastc.anickd.lib.SpinAdapter;
import com.tomastc.anickd.lib.User;
import com.tomastc.anickd.lib.common.AsyncHttpClient;
import com.tomastc.anickd.lib.common.CallbackListener;
import com.tomastc.anickd.lib.common.CustomEditText;
import com.tomastc.anickd.lib.common.DrawableClickListener;
import com.tomastc.anickd.lib.common.MessageListener;
import com.tomastc.anickd.lib.common.Utils;

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

import java.util.HashMap;

import okhttp3.WebSocket;

public class MainActivity extends Scanner implements
        CallbackListener, MessageListener {

    private Button btn_login, btn_receiving_area, btn_staging_area, btn_outer_area, btn_print_tag, btn_close,btn_printer_setting;
    private TextView lbl_main_title, lbl_err, lbl_version;
    private CustomEditText txt_password;
    private RelativeLayout layout_login, layout_menu;

    private SpinAdapter usrListArrayAdapter;

    private static int title_click = 0;
    public static WsClient wsClient = null;

    public static MainActivity instance = null;

    public static JSONArray pendingMasterJsonArray = null;
    public static HashMap<String, User> userHashMap = null;

    // Make timer for keep alive
    private static final int interval = 60000; // 60 Seconds
    private static Handler handler = new Handler();
    private static Runnable runnable = new Runnable(){
        public void run() {
            //Toast.makeText(MainActivity.this, "Keep alive...", Toast.LENGTH_SHORT).show();
            if (wsClient != null && wsClient.isConnected()) {
                try {
                    JSONObject j_ext = new JSONObject();
                    j_ext.put("user_id", Settings.getUser());
                    j_ext.put("device_id", Settings.getDeviceNo());
                    j_ext.put("device_type", MainActivity.instance.getString(R.string.device_type));
                    WsClient.getInstance().sendMessage(
                            WsProtocol.encapsulation(
                                    WsProtocol.COMMAND.PING.toString(),
                                    j_ext
                            )
                    );
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                // Silent reconnect
                wsClient.connect();
            }

            handler.postDelayed(runnable, interval);
        }
    };

    private void downloadPendingReason() {
        // download user data from web
        try {
            JSONObject json = new JSONObject();
            json.put("cmd", "inquiry");
            new AsyncHttpClient(getApplicationContext()
                    ,Settings.getMgmtList().get("web_api") + "/pending_master.php"
                    , json.toString()
            ) {
                @Override
                public void onFinished(String response, int resp_code) {
                    Log.d(getString(R.string.tag), "response: " + response);
                    // update mapItems
                    try {
                        pendingMasterJsonArray = new JSONArray(response);
                    } catch (JSONException e) {
                        Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
                    }
                }
            }
                    .execute();
        } catch (JSONException e) {
            Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
        }
    }

    private void downloadUser() {// 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 {
                        userHashMap = new HashMap<>();
                        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");

                            users[i] = new User(id, name, password, dept, role, status);

                            userHashMap.put(id, users[i]);
                        }

                        // Setup user list
                        Spinner ddl_user = findViewById(R.id.ddl_user);
                        usrListArrayAdapter = new SpinAdapter(
                                getApplicationContext(), R.layout.spinner_usr_list, users);
                        ddl_user.setAdapter(usrListArrayAdapter);

                    } catch (JSONException e) {
                        Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
                    }
                }
            }
                    .execute();
        } catch (JSONException e) {
            Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
        }
    }

    private void init() {

        downloadUser();
        downloadPendingReason();
    }

    @Override
    public void processData(String data, DecodeResult.Result result, String codeType) {

        try {

            Log.d(getString(R.string.tag), "data read:" + data);

            User user = (User)usrListArrayAdapter.findItem(data);
            if (user != null) {
                int pos = usrListArrayAdapter.getPosition(user);
                Log.d(getString(R.string.tag), "user list index:" + pos);
                ((Spinner) findViewById(R.id.ddl_user)).setSelection(pos);

                //txt_password.requestFocus();
            } else {
                Toast.makeText(getApplicationContext(), "User ID[" + data + "] not found!",
                        Toast.LENGTH_LONG).show();
            }

            // always hide keyboard after scan
            Utils.hideKeyboardFrom(getApplicationContext(), default_view);
            txt_password.requestFocus();

        } catch (Exception e) {
            Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
        }
    }

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

        instance = this;

        default_view = (EditText) findViewById(R.id.txt_tmp);

        // read settings from Internal storage
        Settings.init(MainActivity.this);

        // Layout
        layout_login = (RelativeLayout) findViewById(R.id.layout_login);
        layout_menu = (RelativeLayout) findViewById(R.id.layout_menu);

        // Visibility
        layout_login.setVisibility(RelativeLayout.VISIBLE);
        layout_menu.setVisibility(RelativeLayout.GONE);

        // Button
        btn_login = (Button) findViewById(R.id.btn_login);
        btn_receiving_area = (Button) findViewById(R.id.btn_receiving);
        btn_staging_area = (Button) findViewById(R.id.btn_staging);
        btn_outer_area = (Button) findViewById(R.id.btn_outer);
        btn_close = (Button) findViewById(R.id.btn_close);
        btn_print_tag = (Button)findViewById(R.id.btn_print_tag);
        btn_printer_setting = (Button)findViewById(R.id.btn_printer_setting);

        // Textview
        lbl_main_title = (TextView) findViewById(R.id.lbl_main_title);
        lbl_err = (TextView) findViewById(R.id.lbl_err);
        lbl_version = (TextView) findViewById(R.id.lbl_version);

        lbl_version.setText("v." + BuildConfig.VERSION_NAME);

        txt_password = (CustomEditText) findViewById(R.id.txt_password);
        txt_password.requestFocus();

        txt_password.setDrawableClickListener(new DrawableClickListener() {
            public void onClick(DrawableClickListener.DrawablePosition target) {
                switch (target) {
                    case RIGHT:
                        //Do something here
                        txt_password.setText("");
                        break;

                    default:
                        break;
                }
            }

        });

        // Hidden screen
        lbl_main_title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                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(MainActivity.this, SettingsActivity.class);
                    startActivity(intent);
                }
            }
        });

        // Button click event
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int selected_id = ((Spinner) findViewById(R.id.ddl_user)).getSelectedItemPosition();
                String username = usrListArrayAdapter.getItem(selected_id).getName();

                if (!txt_password.getText().toString().equals(
                        ((User)usrListArrayAdapter.getItem(selected_id)).getPassword() )) {
                    Toast.makeText(getApplicationContext(), "Password wrong!", Toast.LENGTH_LONG).show();
                    Utils.playTones(ToneGenerator.TONE_CDMA_ABBR_ALERT, 10000, 900);

                    return;
                }

                // Set username label
                Settings.setLoginUser((User)usrListArrayAdapter.getItem(selected_id));
                TextView label_username = (TextView) findViewById(R.id.lbl_user_code);
                label_username.setText(Settings.getLoginUser().getName());

                // Set HT device id <== read from INI
                TextView label_device_id = (TextView) findViewById(R.id.lbl_device_no);
                label_device_id.setText(Settings.getDeviceNo());

                // Discard the ScanManager class instance.
                mScanManager.removeDataListener(MainActivity.this);
                // Discard the ScanManager class instance to release the resources.
                mScanManager.releaseScanManager();

                layout_login.setVisibility(RelativeLayout.GONE);
                layout_menu.setVisibility(RelativeLayout.VISIBLE);

                // Connect to web socket server
                if (Settings.getMgmtList().containsKey("ws_node")) {
                    wsClient = WsClient.getInstance(
                            MainActivity.this
                            , MainActivity.this
                            , getApplicationContext()
                            , Settings.getMgmtList().get("ws_node"));
                }
            }
        });
        btn_receiving_area.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(getString(R.string.tag), "start receiving activity");
                Intent intent =new Intent(MainActivity.this, ReceivingActivity.class);
                startActivity(intent);
            }
        });
        btn_staging_area.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(getString(R.string.tag), "start NG label activity");
                Intent intent =new Intent(MainActivity.this, StagingActivity_Phase3.class);
                startActivity(intent);
            }
        });
        btn_outer_area.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(getString(R.string.tag), "start NG label activity");
                Intent intent =new Intent(MainActivity.this, OuterActivity.class);
                startActivity(intent);
            }
        });

        btn_print_tag.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent =new Intent(MainActivity.this, PrintTagActivity.class);
                startActivity(intent);
            }
        });

        btn_printer_setting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent =new Intent(MainActivity.this, PrinterSettingActivity.class);
                startActivity(intent);
            }
        });
        btn_close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (WsClient.getInstance()!=null) {
                    if (WsClient.getInstance().isConnected()) {

                        try {
                            JSONObject j_ext = new JSONObject();

                            j_ext = new JSONObject();
                            j_ext.put("user_id", Settings.getLoginUser().getId());
                            j_ext.put("device_id", Settings.getDeviceNo());
                            j_ext.put("device_type", getString(R.string.device_type));
                            WsClient.getInstance().sendMessage(
                                    WsProtocol.encapsulation(
                                            WsProtocol.COMMAND.UNREGISTER_REQUEST.toString(),
                                            j_ext
                                    )
                            );
                        } catch (Exception e) {
                            Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
                        }
                    }
                }

                finishAffinity();
                System.exit(0);
            }
        });

        // initial
        init();
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        //Log.d(getString(R.string.tag), String.format("keyCode: %d", keyCode) );
        if (keyCode >= KeyMapping.P1.getId()
            && keyCode <= KeyMapping.P4.getId())
        {
            switch (KeyMapping.fromId(keyCode)) {
                case P1:
                    finishAffinity();
                    System.exit(0);
                    break;

                case P2:
                    btn_receiving_area.performClick();
                    break;

                case P3:
                    btn_staging_area.performClick();
                    break;

                case P4:
                    btn_outer_area.performClick();
                    break;

            }
        } else if (keyCode == KeyMapping.ENT.getId()) {
            if (layout_login.getVisibility() == View.VISIBLE) {
                Log.d(getString(R.string.tag), "do button perform click");
                btn_login.requestFocus();
                btn_login.performClick();
            }
            return false;
        }
        /*
        else if (keyCode >= 7 && keyCode <= 16) {
            if (layout_login.getVisibility() == View.VISIBLE) {
                if (!txt_password.isFocused()) {
                    txt_password.requestFocus();
                    return false;
                }
            }
        }
         */

        return super.onKeyUp(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onFinished(String result) {
        Log.d(getString(R.string.tag), "onFinished() on class " + getLocalClassName() + "|result:" + 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(
                            MainActivity.this
                            , MainActivity.this
                            , getApplicationContext()
                            , Settings.getMgmtList().get("ws_node"));
                }
            }

            try {
                JSONObject j_ext = new JSONObject();
                j_ext.put("user_id", Settings.getLoginUser().getId());
                j_ext.put("device_id", Settings.getDeviceNo());
                j_ext.put("device_type", getString(R.string.device_type));
                WsClient.getInstance().sendMessage(
                        WsProtocol.encapsulation(
                                WsProtocol.COMMAND.RESET_REQUEST.toString(),
                                j_ext
                        )
                );
            } catch (Exception e) {
                Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
            }
        } else {
            // Connect to web socket server
            if (Settings.getMgmtList().containsKey("ws_node")
                    && Settings.getLoginUser()!=null) {
                wsClient = WsClient.getInstance(
                        MainActivity.this
                        , MainActivity.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));

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

            switch (WsProtocol.COMMAND.valueOf(jsonObject.getString("cmd"))) {
                case HELLO:
                    j_ext = new JSONObject(jsonObject.getString("ext"));
                    WsClient.getInstance().client_id = j_ext.getInt("id");

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

                case REGISTER_ACK:
                    WsClient.getInstance().status = WsClient.STATUS.IDLE;
                    break;
            }
        } catch (JSONException e) {
            Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
        } catch (Exception e) {
            Log.e(getString(R.string.tag), "ERROR:" + e.getMessage());
        }
    }


}