package com.tomastc.anickd;

import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static com.tomastc.anickd.lib.ErrorCode.E105;
import static com.tomastc.anickd.lib.ErrorCode.E106;
import static com.tomastc.anickd.lib.ErrorCode.E110;
import static com.tomastc.anickd.lib.ErrorCode.E111;
import static com.tomastc.anickd.lib.ErrorCode.E112;
import static com.tomastc.anickd.lib.ErrorCode.E114;
import static com.tomastc.anickd.lib.ErrorCode.E115;
import static com.tomastc.anickd.lib.ErrorCode.E116;
import static com.tomastc.anickd.lib.ErrorCode.E122;
import static com.tomastc.anickd.lib.ErrorCode.E124;
import static com.tomastc.anickd.lib.ErrorCode.E203;

import android.content.Context;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.media.ToneGenerator;
import android.os.Bundle;
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.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

import com.keyence.autoid.sdk.scan.DecodeResult;
import com.tomastc.anickd.lib.CkdInterface;
import com.tomastc.anickd.lib.KeyMapping;
import com.tomastc.anickd.lib.Settings;
import com.tomastc.anickd.lib.SpinAdapter;
import com.tomastc.anickd.lib.User;
import com.tomastc.anickd.lib.common.CallbackListener;
import com.tomastc.anickd.lib.common.MessageListener;
import com.tomastc.anickd.lib.common.ScrollToTrick;
import com.tomastc.anickd.lib.common.StringConvert;
import com.tomastc.anickd.lib.common.StringUtil;
import com.tomastc.anickd.lib.common.Utils;
import com.tomastc.anickd.R;
import com.tomastc.anickd.lib.ActionListenerCallback;
import com.tomastc.anickd.lib.ErrorCode;
import com.tomastc.anickd.lib.PendingMaster;
import com.tomastc.anickd.lib.ProductionSchedule;
import com.tomastc.anickd.lib.Scanner;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;

import okhttp3.WebSocket;

public class StagingActivity extends Scanner implements
        CallbackListener, MessageListener, CkdInterface {
    
    private String job_id; // Random hash 32
    private Button btn_main_menu, btn_clear, btn_pending, btn_ng
            , btn_answer1, btn_answer2, btn_answer3, btn_answer4;
    private EditText txt_pc_no, txt_part_no, txt_part_color, txt_control_no, txt_qty, txt_maker;
    private TextView txt_chk_point1, txt_chk_point2, txt_chk_point3, txt_chk_point4, lbl_tablet_no, lbl_open_meiji_card;
    private TableLayout tbl_schedules_table;
    private RelativeLayout content_page1, content_page2, content_page3, popupLayout1, popupLayout2;
    private SpinAdapter pendingSpinAdapter=null, ngSpinAdapter=null;

    private Map<String, JSONObject> mapItems = new LinkedHashMap<>();

    private int scan_step = 0;
    private boolean waiting_ws_response = false;
    private boolean screen_locked = false;

    private int staging_act_qty = 0;

    private ProductionSchedule.STAGE stage = ProductionSchedule.STAGE.STAGING;

    private String s_qty, part_no, part_color, pc_no, control_no;

    // Version 1.4.10 : Support to check the packing_no
    private String packing_no;

    private JSONObject meiji_card_schedule, j_ext, checkpoint;
    private JSONArray meiji_card_schedules;

    private void redrawSchedulesTable() {

        Log.d(getString(R.string.tag), "redrawSchedulesTable() called");

        try {
            content_page3.setVisibility(VISIBLE);
            Context context = getApplicationContext();

            // clear tbl_serial_scan
            tbl_schedules_table.removeAllViews();

            int i = 0;
            Comparator<JSONObject> comparator = (JSONObject o1, JSONObject o2) -> {
                try {
                    if (o1.getString("model_no").equalsIgnoreCase("PPP"))
                        return o1.getInt("item_no") - o2.getInt("item_no");
                    else
                        return o1.getInt("case_packing_seq") - o2.getInt("case_packing_seq");
                } catch (Exception e) {
                    return 0;
                }
            };
            SortedSet<JSONObject> items = new TreeSet<>(comparator);
            items.addAll(mapItems.values());
            for (JSONObject item : items) {

                Log.d(getString(R.string.tag), "Item id : " + item.getString("id"));

                int bgColor = Color.argb((++i%2) == 0 ? 0x30 : 0x10, 0xaa, 0xaa, 0xaa);
                int bgColorStatus = bgColor;
                int bgColorYellow = Color.argb(0xff, 0xff, 0xff, 0x00);
                int bgColorGreen = Color.argb(0xff, 0x00, 0xff, 0x00);

                //JSONObject item = mapItems.get(key);
                String seq_no = item.getString(
                        item.getString("model_no").equalsIgnoreCase("PPP") ? "packing_no" : "case_packing_seq");
                String part_no = item.getString("part_no");
                int plan_qty = item.getInt("staging_plan_qty");
                int act_qty = item.getInt("staging_act_qty");


                //new table design for staging/outer, it is only 1 case specific
                String s_qty = String.format("%d/%d", act_qty, plan_qty);

                if (act_qty >= plan_qty) {
                    bgColorStatus = bgColorGreen;
                } else if (act_qty > 0) {
                    bgColorStatus = bgColorYellow;
                }

                TableRow tableRow = new TableRow(context);
                TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
                layoutParams.setMargins(1,1,1,1);
                tableRow.setLayoutParams(layoutParams);
                tableRow.setTag(item.getString("id"));

                TextView textView = new TextView(context);
                textView.setText(seq_no);
                textView.setWidth(45);
                textView.setHeight(30);
                textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
                textView.setBackgroundColor(bgColor);
                textView.setPadding(1,5,0,0);
                textView.setLayoutParams(layoutParams);
                tableRow.addView(textView);

                textView = new TextView(context);
                textView.setText(part_no);
                textView.setHeight(30);
                textView.setBackgroundColor(bgColor);
                textView.setPadding(1,5,0,0);
                textView.setLayoutParams(layoutParams);
                tableRow.addView(textView);

                textView = new TextView(context);
                textView.setText(s_qty);
                textView.setWidth(60);
                textView.setHeight(30);
                textView.setBackgroundColor(bgColorStatus);
                textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
                textView.setPadding(1,5,0,0);
                textView.setLayoutParams(layoutParams);
                tableRow.addView(textView);

                tableRow.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        meiji_card_schedule = mapItems.get(v.getTag());
                        try {
                            if (meiji_card_schedule.getInt("staging_plan_qty") == meiji_card_schedule.getInt("staging_act_qty")) {
                                alertOk("This job has already finished.", new ActionListenerCallback() {
                                    @Override
                                    public void onActionSuccess(String successMessage) throws Exception {

                                    }

                                    @Override
                                    public void onActionFailure(Throwable throwableError) {

                                    }
                                });
                            } else {
                                lbl_open_meiji_card.setText("Ready to scan tag receive.");
                                lbl_open_meiji_card.setTextColor(getColor(R.color.green));

                                content_page3.setVisibility(INVISIBLE);
                            }
                        } catch (JSONException e) {

                        }
                    }
                });

                tbl_schedules_table.addView(tableRow);

            }

        } catch (Exception e) {
            Log.e(getString(R.string.tag), e.getMessage());
            e.printStackTrace();
        }

    }

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

        //if (waiting_ws_response) {
        if (waiting_ws_response
            && Settings.getMgmtList().get("HT_WAIT_SERVER_RESPONSE").equals("1")
        ) {
            alertOk("Please waiting for server response.", new ActionListenerCallback() {
                @Override
                public void onActionSuccess(String successMessage) {
                }

                @Override
                public void onActionFailure(Throwable throwableError) {

                }
            });
            return;
        }

        if (screen_locked) {
            EditText txt_leader_password = (EditText) findViewById(R.id.txt_leader_password);
            txt_leader_password.setEnabled(false);
            txt_leader_password.setText(data);
            Button btn = (Button) findViewById(R.id.popupLayout2_btn1);
            btn.performClick();
            return;
        }

        if (meiji_card_schedules == null) {
            alertError("Please open meiji card.", new ActionListenerCallback() {
                @Override
                public void onActionSuccess(String successMessage) {
                    // Test only
                    boolean test_mode = false;
                    if (test_mode)
                    try {
                        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));
                        j_ext.put("schedule_id", 91);
                        j_ext.put("event", WsProtocol.EVENT.TB_STAGING_MONITOR_MEIJI_CARD_SUCCESS);
                        j_ext.put("status", ProductionSchedule.STATUS.WORKING);
                        j_ext.put("stage", stage);
                        WsClient.getInstance().sendMessage(
                                WsProtocol.encapsulation(
                                        WsProtocol.COMMAND.EVENT_LOG_REQUEST.toString(),
                                        j_ext
                                )
                        );
                    } catch (Exception e) {
                        Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
                        alertError(e.getMessage(), new ActionListenerCallback() {
                            @Override
                            public void onActionSuccess(String successMessage) throws Exception {

                            }

                            @Override
                            public void onActionFailure(Throwable throwableError) {

                            }
                        }, screen_locked=false);
                    }



                }

                @Override
                public void onActionFailure(Throwable throwableError) {

                }
            }, screen_locked=false);
            return;
        }

        try {

            Log.d(getString(R.string.tag), String.format("data read[%d bytes]: %s", data.length(), data));

            switch (scan_step) {
                case 0:
                    // Format: PART_NO[29] + PART_NAME[30] + PART_COLOR[7] + PC_NO[15] + CONTROL_NO[7] + QTY[7]
                    // Length: 143
                    // Other:

                    if (data.length()<143) {
                        alertError(E110.toString(), new ActionListenerCallback() {
                            @Override
                            public void onActionSuccess(String successMessage) throws Exception {

                            }

                            @Override
                            public void onActionFailure(Throwable throwableError) {

                            }
                        }, screen_locked=false);
                        throw new Exception(E110.toString());
                    }

                    part_no = data.substring(0, 29).trim(); // 12251-59B -0040   (0043) --> 1225159B 0043 (design part no)
                    /**
                     * Version < 1.4.8
                     *
                    part_color = data.substring(59, 66).trim(); // ABCDE
                    pc_no = data.substring(66, 81).trim(); // 373-34A-5678-18
                    control_no = data.substring(81, 88).trim(); // 149-06
                    s_qty = data.substring(88, 95).trim(); // 60
                    String model_no = data.substring(115, 118); // PPP
                    if (model_no.equalsIgnoreCase("PPP"))
                        control_no = data.substring(130, 134);
                     */
                    part_color = data.substring(59, 70).trim(); // ABCDE
                    pc_no = data.substring(70, 85).trim(); // 373-34A-5678-18
                    control_no = data.substring(85, 92).trim(); // 149-06
                    s_qty = data.substring(92, 99).trim(); // 60
                    String model_no = data.substring(119, 122); // PPP
                    if (model_no.equalsIgnoreCase("PPP"))
                        control_no = data.substring(134, 138).trim();

                    // Version 1.4.10 : Support to check the packing_no
                    packing_no = data.substring(85, 92).trim(); // 149-06, PPP: 025-002
                    String[] tmp2_ = StringUtil.doScanner(packing_no, "[\\d\\w]{1,}-[0]{1,}([\\d]{1,})");
                    if (tmp2_.length > 0)
                        packing_no = tmp2_[0];

                    // Reformat input
                    String p = "([\\d\\w]{5})-([\\d\\w]{3})\\s-[\\d\\w\\-]{4,}\\s+\\(([\\w\\d\\-]{4,})\\).*";
                    String[] tmp_ = StringUtil.doScanner(part_no, p);
                    Log.d(getString(R.string.tag), String.format("part_no : \"%s\"", part_no));
                    Log.d(getString(R.string.tag), Arrays.deepToString(tmp_));
                    if (tmp_.length == 3) {
                        part_no = String.format("%s%s %s", tmp_[0], tmp_[1], tmp_[2]).replace("-", "");;
                    }
                    part_no = part_no.replace("-", "").trim();
                    pc_no = pc_no.replace("-", "");

                    Log.d(getString(R.string.tag), String.format("%s,%s,%s,%s,%s,%s"
                            , part_no, part_color, pc_no, control_no, s_qty, model_no));

                    // Matching with data scan
                    if (meiji_card_schedule.getString("pc_no").equalsIgnoreCase(pc_no)
                            && meiji_card_schedule.getString("part_no").equalsIgnoreCase(part_no)
                            && meiji_card_schedule.getString("part_color").equalsIgnoreCase(part_color)
                            // check only first 3 digits for non PBP
                            && (
                                (meiji_card_schedule.getString("control_no").substring(0,3).equalsIgnoreCase(control_no.substring(0,3))
                                        && !meiji_card_schedule.getString("model_no").equals("PPP"))
                                || (meiji_card_schedule.getString("control_no").substring(0,4).equalsIgnoreCase(control_no.substring(0,4))
                                        && meiji_card_schedule.getString("model_no").equals("PPP"))
                            // Version 1.4.10 : Support to check the packing_no
                            && meiji_card_schedule.getInt("packing_no") == Integer.parseInt(packing_no)
                            )
                    ) {
                        // show and choose the schedule
                        WsClient.sendWsEventLog(StagingActivity.this,
                                new HashMap<String, Object>() {{
                                    put("part_no", part_no);
                                    put("part_color", part_color);
                                    put("schedule_id", meiji_card_schedule.getString("id"));
                                    // v1.4.7
                                    put("model_no", meiji_card_schedule.getString("model_no"));
                                }}
                                , WsProtocol.EVENT.HT_STAGING_SCAN_STEP1_SUCCESS
                                , ProductionSchedule.STATUS.WORKING
                        );

                        // Update display
                        txt_pc_no.setText(pc_no);
                        txt_part_no.setText(part_no);
                        txt_part_color.setText(part_color);
                        txt_control_no.setText(control_no);
                        txt_maker.setText(meiji_card_schedule.getString("maker_code"));
                        staging_act_qty = 0;
                        try {
                            staging_act_qty = meiji_card_schedule.getInt("staging_act_qty");
                        } catch (Exception e) {

                        }
                        txt_qty.setText( String.valueOf(
                                meiji_card_schedule.getInt("staging_plan_qty")
                                - staging_act_qty
                                )
                        );

                        scan_step++;

                        Toast.makeText(StagingActivity.this, "Scan data OK.", Toast.LENGTH_LONG)
                                .show();

                    } else {
                        // not match NG
                        WsClient.sendWsEventLog(StagingActivity.this,
                                new HashMap<String, Object>() {{
                                    put("error_code", E106.getId());
                                    put("error_det", E106.getDet());
                                    put("schedule_id", meiji_card_schedule.getString("id"));
                                }}
                                , WsProtocol.EVENT.HT_STAGING_SCAN_STEP1_FAILED
                                , ProductionSchedule.STATUS.NG
                        );

                        alertError("Non-matched\n" + E106.toString(), new ActionListenerCallback() {
                            @Override
                            public void onActionSuccess(String successMessage) throws Exception {

                            }

                            @Override
                            public void onActionFailure(Throwable throwableError) {
                                ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                                Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                        .show();
                                try {
                                    WsClient.sendWsEventLog(StagingActivity.this,
                                            new HashMap<String, Object>() {{
                                                put("event_det", WsProtocol.EVENT.HT_STAGING_SCAN_STEP1_FAILED);
                                                put("error_code", errorCode.getId());
                                                put("error_det", errorCode.getDet());
                                            }}
                                            , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                            , ProductionSchedule.STATUS.NG
                                    );
                                } catch (Exception e) {
                                    Log.e(getString(R.string.tag), e.getMessage());
                                }
                            }
                        }, screen_locked=true);
                    }

                    break;
            }

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

        } catch (Exception e) {
            Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
            alertError("Please try again!!", new ActionListenerCallback() {
                @Override
                public void onActionSuccess(String successMessage) throws Exception {

                }

                @Override
                public void onActionFailure(Throwable throwableError) {

                }
            }, screen_locked=false);
        }
    }

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

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

        // update MessageListener class
        WsClient.getInstance().setOnMessageListener(this);

        btn_main_menu = (Button) findViewById(R.id.btn_main_menu);
        btn_clear = (Button) findViewById(R.id.btn_clear);
        btn_pending = (Button) findViewById(R.id.btn_pending);
        btn_ng = (Button) findViewById(R.id.btn_ng);
        btn_answer1 = (Button) findViewById(R.id.btn_answer1);
        btn_answer2 = (Button) findViewById(R.id.btn_answer2);
        btn_answer3 = (Button) findViewById(R.id.btn_answer3);
        btn_answer4 = (Button) findViewById(R.id.btn_answer4);
        btn_main_menu.requestFocus();

        tbl_schedules_table = (TableLayout)findViewById(R.id.tbl_schedules_table);

        txt_pc_no = (EditText) findViewById(R.id.txt_pc_no);
        txt_part_no = (EditText) findViewById(R.id.txt_part_no);
        txt_part_color = (EditText) findViewById(R.id.txt_part_color);
        txt_control_no = (EditText) findViewById(R.id.txt_control_no);
        txt_qty = (EditText) findViewById(R.id.txt_qty);
        txt_maker = (EditText) findViewById(R.id.txt_maker);
        txt_chk_point1 = (TextView) findViewById(R.id.txt_chk_point1);
        txt_chk_point2 = (TextView) findViewById(R.id.txt_chk_point2);
        txt_chk_point3 = (TextView) findViewById(R.id.txt_chk_point3);
        txt_chk_point4 = (TextView) findViewById(R.id.txt_chk_point4);
        lbl_tablet_no = (TextView) findViewById(R.id.lbl_tablet_no);
        lbl_open_meiji_card = (TextView) findViewById(R.id.lbl_open_meiji_card);

        content_page1 = (RelativeLayout) findViewById(R.id.content_page1);
        content_page2 = (RelativeLayout) findViewById(R.id.content_page2);
        content_page3 = (RelativeLayout) findViewById(R.id.content_page3);
        popupLayout1 = (RelativeLayout) findViewById(R.id.popupLayout1);
        popupLayout2 = (RelativeLayout) findViewById(R.id.popupLayout2);

        Utils.hideKeyboardFrom(getApplicationContext(), txt_qty);
        reset();

        try {
            // Set AREA
            WsClient.sendWs(StagingActivity.this, new HashMap<String, Object>() {{
                put("area", ProductionSchedule.AREA.STAGING);
            }}, WsProtocol.COMMAND.SET_AREA_REQUEST);

            // Get paired tablet device id
            WsClient.sendWs(StagingActivity.this, null, WsProtocol.COMMAND.GET_PAIRED_DEVICE_REQUEST);
        } catch (Exception e) {
            Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
        }

        btn_main_menu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // stop activity
                finish();
            }
        });
        btn_clear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                reset();
            }
        });
        btn_pending.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Check if no schedule load
                if (scan_step==0) {
                    return;
                }

                // Open pending dialog
                if (pendingSpinAdapter == null) {
                    JSONArray jArray = MainActivity.pendingMasterJsonArray;
                    if (jArray!=null) {

                        try {
                            if (jArray.length() == 0)
                                return;

                            List<PendingMaster> list = new ArrayList<>();
                            for (int i=0;i<jArray.length();i++) {
                                if (jArray.getJSONObject(i).getString("sec").equalsIgnoreCase("pending")) {
                                    String id = jArray.getJSONObject(i).getString("id");
                                    String name = jArray.getJSONObject(i).getString("mesg");

                                    list.add(new PendingMaster(id, name));
                                }
                            }
                            PendingMaster[] pendingMasters = list.toArray(new PendingMaster[0]);

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

                            pendingSpinAdapter = new SpinAdapter(
                                    getApplicationContext(), R.layout.spinner_usr_list, pendingMasters);

                        } catch (Exception e) {
                            Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
                            alertError(e.getMessage(), new ActionListenerCallback() {
                                @Override
                                public void onActionSuccess(String successMessage) throws Exception {

                                }

                                @Override
                                public void onActionFailure(Throwable throwableError) {

                                }
                            }, screen_locked=false);
                        }
                    }
                }

                if (pendingSpinAdapter.getCount() == 0) {
                    alertError(E115.toString(), new ActionListenerCallback() {
                        @Override
                        public void onActionSuccess(String successMessage) throws Exception {

                        }

                        @Override
                        public void onActionFailure(Throwable throwableError) {
                            ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                            Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                    .show();
                            try {
                                WsClient.sendWsEventLog(StagingActivity.this,
                                        new HashMap<String, Object>() {{
                                            put("event_det", WsProtocol.EVENT.HT_STAGING_PENDING);
                                            put("error_code", errorCode.getId());
                                            put("error_det", errorCode.getDet());
                                        }}
                                        , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                        , ProductionSchedule.STATUS.NG
                                );
                            } catch (Exception e) {
                                Log.e(getString(R.string.tag), e.getMessage());
                            }

                        }
                    }, screen_locked=true);

                    return;
                }

                confirmation("Please select the reason for pending."
                        , getColor(R.color.red)
                        , true
                        , new ActionListenerCallback() {
                            @Override
                            public void onActionSuccess(String successMessage) throws Exception {

                                // Notify to server
                                WsClient.sendWsEventLog(StagingActivity.this,
                                        new HashMap<String, Object>() {{
                                            put("event_det", successMessage);
                                            put("schedule_id", meiji_card_schedule.getString("id"));
                                        }}
                                        , WsProtocol.EVENT.HT_STAGING_PENDING
                                        , ProductionSchedule.STATUS.PENDING
                                );

                                alertOk("Pending saved.", new ActionListenerCallback() {
                                    @Override
                                    public void onActionSuccess(String successMessage) throws Exception {
                                        reset();
                                    }

                                    @Override
                                    public void onActionFailure(Throwable throwableError) {

                                    }
                                });
                            }

                            @Override
                            public void onActionFailure(Throwable throwableError) {

                            }
                        }, pendingSpinAdapter);
            }
        });
        btn_ng.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Check if no schedule load
                if (scan_step == 0) {
                    return;
                }
                // Open NG dialog
                if (ngSpinAdapter == null) {
                    JSONArray jArray = MainActivity.pendingMasterJsonArray;
                    if (jArray!=null) {

                        try {
                            if (jArray.length() == 0)
                                return;

                            List<PendingMaster> list = new ArrayList<>();
                            for (int i=0;i<jArray.length();i++) {
                                if (jArray.getJSONObject(i).getString("sec").equalsIgnoreCase("ng")) {
                                    String id = jArray.getJSONObject(i).getString("id");
                                    String name = jArray.getJSONObject(i).getString("mesg");

                                    list.add(new PendingMaster(id, name));
                                }
                            }
                            PendingMaster[] pendingMasters = list.toArray(new PendingMaster[0]);

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

                            ngSpinAdapter = new SpinAdapter(
                                    getApplicationContext(), R.layout.spinner_usr_list, pendingMasters);

                        } catch (Exception e) {
                            Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
                            alertError(e.getMessage(), new ActionListenerCallback() {
                                @Override
                                public void onActionSuccess(String successMessage) throws Exception {

                                }

                                @Override
                                public void onActionFailure(Throwable throwableError) {

                                }
                            }, screen_locked=false);
                        }
                    }
                }

                if (ngSpinAdapter.getCount() == 0) {
                    alertError(E116.toString(), new ActionListenerCallback() {
                        @Override
                        public void onActionSuccess(String successMessage) throws Exception {

                        }

                        @Override
                        public void onActionFailure(Throwable throwableError) {
                            ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                            Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                    .show();
                            try {
                                WsClient.sendWsEventLog(StagingActivity.this,
                                        new HashMap<String, Object>() {{
                                            put("event_det", WsProtocol.EVENT.HT_STAGING_NG);
                                            put("error_code", errorCode.getId());
                                            put("error_det", errorCode.getDet());
                                        }}
                                        , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                        , ProductionSchedule.STATUS.NG
                                );
                            } catch (Exception e) {
                                Log.e(getString(R.string.tag), e.getMessage());
                            }

                        }
                    }, screen_locked=true);

                    return;
                }

                confirmation("Please select the reason for NG."
                        , getColor(R.color.red)
                        , true
                        , new ActionListenerCallback() {
                            @Override
                            public void onActionSuccess(String successMessage) throws Exception {

                                // Notify to server
                                WsClient.sendWsEventLog(StagingActivity.this,
                                        new HashMap<String, Object>() {{
                                            put("event_det", successMessage);
                                            put("schedule_id", meiji_card_schedule.getString("id"));
                                        }}
                                        , WsProtocol.EVENT.HT_STAGING_NG
                                        , ProductionSchedule.STATUS.NG
                                );

                                alertOk("NG saved.", new ActionListenerCallback() {
                                    @Override
                                    public void onActionSuccess(String successMessage) throws Exception {
                                        reset();
                                    }

                                    @Override
                                    public void onActionFailure(Throwable throwableError) {

                                    }
                                });
                            }

                            @Override
                            public void onActionFailure(Throwable throwableError) {

                            }
                        }, ngSpinAdapter);

            }
        });
        btn_answer1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkpoint_check(btn_answer1.getText().toString());
            }
        });
        btn_answer2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkpoint_check(btn_answer2.getText().toString());
            }
        });
        btn_answer3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkpoint_check(btn_answer3.getText().toString());
            }
        });
        btn_answer4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkpoint_check(btn_answer4.getText().toString());
            }
        });
    }

    private void checkpoint_check(String ans) {
        Log.d(getString(R.string.tag), "check answer: " + ans);
        if (checkpoint != null) {
            try {
                // check remaining qty
                int remaining = meiji_card_schedule.getInt("staging_plan_qty")
                        - staging_act_qty;

                if (txt_qty.getText().toString().isEmpty()
                || Integer.parseInt(txt_qty.getText().toString()) > remaining) {
                    // matched
                    alertError("Qty[" + txt_qty.getText() + "] is exceed the plan or invalid."
                            , new ActionListenerCallback() {
                        @Override
                        public void onActionSuccess(String successMessage) throws Exception {
                        }

                        @Override
                        public void onActionFailure(Throwable throwableError) {

                        }
                    }, false);
                    return;
                }

                // check checkpoint answer
                if (ans.equalsIgnoreCase(checkpoint.getString("accept_choice"))) {
                    // matched
                    alertOk("matched", new ActionListenerCallback() {
                        @Override
                        public void onActionSuccess(String successMessage) throws Exception {
                            reset();
                        }

                        @Override
                        public void onActionFailure(Throwable throwableError) {

                        }
                    });
                    Utils.playNotification(getApplicationContext(), RingtoneManager.TYPE_NOTIFICATION);

                    WsClient.sendWsEventLog(StagingActivity.this,
                            new HashMap<String, Object>() {{
                                put("qty", Integer.parseInt(txt_qty.getText().toString()));
                                put("schedule_id", meiji_card_schedule.getString("id"));
                            }}
                            , WsProtocol.EVENT.HT_STAGING_CHECKPOINT_SUCCESS
                            , Integer.parseInt(txt_qty.getText().toString()) < remaining
                                    ? ProductionSchedule.STATUS.WORKING
                                    : ProductionSchedule.STATUS.STAGED
                    );
                } else {
                    // not match NG
                    alertError("Non-matched\n" + E105.toString(), new ActionListenerCallback() {
                        @Override
                        public void onActionSuccess(String successMessage) throws Exception {

                        }

                        @Override
                        public void onActionFailure(Throwable throwableError) {
                            ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                            Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                    .show();
                            try {
                                WsClient.sendWsEventLog(StagingActivity.this,
                                        new HashMap<String, Object>() {{
                                            put("event_det", WsProtocol.EVENT.HT_STAGING_CHECKPOINT_FAILED);
                                            put("error_code", errorCode.getId());
                                            put("error_det", errorCode.getDet());
                                        }}
                                        , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                        , ProductionSchedule.STATUS.NG
                                );
                            } catch (Exception e) {
                                Log.e(getString(R.string.tag), e.getMessage());
                            }

                        }
                    }, screen_locked=true);

                    WsClient.sendWsEventLog(StagingActivity.this,
                            new HashMap<String, Object>() {{
                                put("error_code", E105.getId());
                                put("error_det", E105.getDet());
                                put("schedule_id", meiji_card_schedule.getString("id"));
                            }}
                            , WsProtocol.EVENT.HT_STAGING_CHECKPOINT_FAILED
                            , ProductionSchedule.STATUS.NG
                    );
                }
            } catch (Exception e) {
                Log.e(getString(R.string.tag), "ERROR: " + e.getMessage());
                alertError(e.getMessage(), new ActionListenerCallback() {
                    @Override
                    public void onActionSuccess(String successMessage) throws Exception {

                    }

                    @Override
                    public void onActionFailure(Throwable throwableError) {

                    }
                }, screen_locked=false);
            }
        } else {
            alertError(E114.toString(), new ActionListenerCallback() {
                @Override
                public void onActionSuccess(String successMessage) throws Exception {

                }

                @Override
                public void onActionFailure(Throwable throwableError) {
                    ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                    Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                            .show();
                    try {
                        WsClient.sendWsEventLog(StagingActivity.this,
                                new HashMap<String, Object>() {{
                                    put("event_det", WsProtocol.EVENT.HT_STAGING_CHECKPOINT_FAILED);
                                    put("error_code", errorCode.getId());
                                    put("error_det", errorCode.getDet());
                                }}
                                , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                , ProductionSchedule.STATUS.NG
                        );
                    } catch (Exception e) {
                        Log.e(getString(R.string.tag), e.getMessage());
                    }
                }
            }, screen_locked=true);
        }
    }

    private void reset() {
        job_id = StringConvert.randomHex(32);
        scan_step = 0;
        checkpoint = null;
        meiji_card_schedule = null;
        meiji_card_schedules = null;

        txt_pc_no.setText("");
        txt_part_no.setText("");
        txt_part_color.setText("");
        txt_control_no.setText("");
        txt_qty.setText("");
        txt_maker.setText("");
        txt_chk_point1.setText("");
        txt_chk_point2.setText("");
        txt_chk_point3.setText("");
        txt_chk_point4.setText("");
        lbl_open_meiji_card.setText("Please open MEIJI CARD.");
        lbl_open_meiji_card.setTextColor(getColor(R.color.red));

        content_page1.setVisibility(VISIBLE);
        content_page2.setVisibility(INVISIBLE);
        content_page3.setVisibility(INVISIBLE);

    }

    @Override
    public void onFinished(String result) {

    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
        waiting_ws_response = false;

        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:
                            j_ext = new JSONObject(jsonObject.getString("ext"));
                            WsClient.getInstance().client_id = j_ext.getInt("id");

                            WsClient.sendWs(StagingActivity.this, null, WsProtocol.COMMAND.REGISTER_REQUEST);
                            break;

                        case DEVICE_PAIRING_NOTIFY_REQUEST:
                            lbl_tablet_no.setText(jsonObject.getJSONObject("ext").getString("device_id"));

                            WsClient.sendWs(StagingActivity.this, null, WsProtocol.COMMAND.DEVICE_PAIRING_NOTIFY_ACK);
                            break;

                        case GET_PAIRED_DEVICE_ACK:
                            lbl_tablet_no.setText("");
                            JSONArray jarry = new JSONArray(jsonObject.getString("ext"));
                            if (jarry.length() > 0) {
                                String tmp = "";
                                for (int i=0; i<jarry.length(); i++) {
                                    tmp = String.format("%s%s%s", tmp, (i>0?",":""), jarry.getJSONObject(i).getString("device_id"));
                                }
                                lbl_tablet_no.setText(tmp);
                            }

                            break;

                        case MEIJI_CARD_READY_REQUEST:
                            meiji_card_schedules = jsonObject.getJSONArray("ext");

                            // Load schedules to table entries
                            mapItems.clear();
                            for (int i=0; i<meiji_card_schedules.length(); i++) {
                                Log.d(getString(R.string.tag), "put schedule id=" + meiji_card_schedules.getJSONObject(i).getString("id"));
                                mapItems.put(meiji_card_schedules.getJSONObject(i).getString("id")
                                        , meiji_card_schedules.getJSONObject(i));
                                Log.d(getString(R.string.tag), "mapItems size=" + mapItems.size());
                            }
                            redrawSchedulesTable();

                            WsClient.sendWs(StagingActivity.this, null, WsProtocol.COMMAND.MEIJI_CARD_READY_ACK);

                            break;

                        case EVENT_LOG_ACK:
                            if (jsonObject.has("ext") && jsonObject.getJSONObject("ext").has("event")) {
                                switch (WsProtocol.EVENT.valueOf(
                                        jsonObject.getJSONObject("ext").getString("event"))) {
                                    case WB_CHECKPOINT_DATA_NOT_FOUND:
                                        alertError(E114.toString(), new ActionListenerCallback() {
                                            @Override
                                            public void onActionSuccess(String successMessage) throws Exception {

                                            }

                                            @Override
                                            public void onActionFailure(Throwable throwableError) {
                                                ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                                                Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                                        .show();
                                                try {
                                                    WsClient.sendWsEventLog(StagingActivity.this,
                                                            new HashMap<String, Object>() {{
                                                                put("event_det", WsProtocol.EVENT.HT_STAGING_CHECKPOINT_FAILED);
                                                                put("error_code", errorCode.getId());
                                                                put("error_det", errorCode.getDet());
                                                            }}
                                                            , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                                            , ProductionSchedule.STATUS.NG
                                                    );
                                                } catch (Exception e) {
                                                    Log.e(getString(R.string.tag), e.getMessage());
                                                }
                                            }
                                        }, screen_locked=true);
                                        break;

                                    case WB_INVALID_CUTPART:
                                        alertError(E124.toString(), new ActionListenerCallback() {
                                            @Override
                                            public void onActionSuccess(String successMessage) throws Exception {
                                            }

                                            @Override
                                            public void onActionFailure(Throwable throwableError) {
                                            }
                                        }, screen_locked=true);
                                        break;

                                    case WB_INVALID_WORKING_STEP:
                                        alertError(E203.toString(), new ActionListenerCallback() {
                                            @Override
                                            public void onActionSuccess(String successMessage) throws Exception {

                                            }

                                            @Override
                                            public void onActionFailure(Throwable throwableError) {
                                                // Just alarm to user
                                                /*
                                                ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                                                Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                                        .show();
                                                try {
                                                    WsClient.sendWsEventLog(StagingActivity.this,
                                                            new HashMap<String, Object>() {{
                                                                put("event_det", WsProtocol.EVENT.WB_INVALID_WORKING_STEP);
                                                                put("error_code", errorCode.getId());
                                                                put("error_det", errorCode.getDet());
                                                            }}
                                                            , WsProtocol.EVENT.WB_INVALID_WORKING_STEP
                                                            , ProductionSchedule.STATUS.NG
                                                    );
                                                } catch (Exception e) {
                                                    Log.e(getString(R.string.tag), e.getMessage());
                                                }
                                                 */
                                            }
                                        }, screen_locked=true);
                                        break;

                                    case HT_STAGING_CHECKPOINT:
                                        // update content page
                                        content_page1.setVisibility(GONE);
                                        content_page2.setVisibility(VISIBLE);

                                        checkpoint = jsonObject.getJSONObject("ext").getJSONObject("event_det");
                                        // random accept choice
                                        int max=4, min=1;
                                        checkpoint.put("accept_choice", String.valueOf(
                                                new Random().nextInt(max - min + 1) + min));

                                        WsClient.sendWsEventLog(StagingActivity.this,
                                                new HashMap<String, Object>() {{
                                                    put("schedule_id", meiji_card_schedule.getString("id"));
                                                }}
                                                , WsProtocol.EVENT.HT_STAGING_CHECKPOINT
                                                , ProductionSchedule.STATUS.WORKING
                                        );

                                        if (checkpoint != null) {
                                            switch (checkpoint.getString("accept_choice")) {
                                                case "1":
                                                    txt_chk_point1.setText(checkpoint.getString("chk_point"));
                                                    txt_chk_point2.setText(checkpoint.getString("dummy1"));
                                                    txt_chk_point3.setText(checkpoint.getString("dummy2"));
                                                    txt_chk_point4.setText(checkpoint.getString("dummy3"));
                                                    break;
                                                case "2":
                                                    txt_chk_point1.setText(checkpoint.getString("dummy1"));
                                                    txt_chk_point2.setText(checkpoint.getString("chk_point"));
                                                    txt_chk_point3.setText(checkpoint.getString("dummy2"));
                                                    txt_chk_point4.setText(checkpoint.getString("dummy3"));
                                                    break;
                                                case "3":
                                                    txt_chk_point1.setText(checkpoint.getString("dummy1"));
                                                    txt_chk_point2.setText(checkpoint.getString("dummy2"));
                                                    txt_chk_point3.setText(checkpoint.getString("chk_point"));
                                                    txt_chk_point4.setText(checkpoint.getString("dummy3"));
                                                    break;
                                                case "4":
                                                    txt_chk_point1.setText(checkpoint.getString("dummy1"));
                                                    txt_chk_point2.setText(checkpoint.getString("dummy2"));
                                                    txt_chk_point3.setText(checkpoint.getString("dummy3"));
                                                    txt_chk_point4.setText(checkpoint.getString("chk_point"));
                                                    break;
                                            }
                                        } else {
                                            // Notify to server
                                            WsClient.sendWsEventLog(StagingActivity.this,
                                                    new HashMap<String, Object>() {{
                                                        put("schedule_id", meiji_card_schedule.getString("id"));
                                                    }}
                                                    , WsProtocol.EVENT.HT_STAGING_CHECKPOINT_FAILED
                                                    , ProductionSchedule.STATUS.WORKING
                                            );

                                            alertError(E114.toString(), new ActionListenerCallback() {
                                                @Override
                                                public void onActionSuccess(String successMessage) throws Exception {

                                                }

                                                @Override
                                                public void onActionFailure(Throwable throwableError) {
                                                    ErrorCode errorCode = ErrorCode.fromId(Integer.parseInt(throwableError.getMessage()));
                                                    Toast.makeText(StagingActivity.this, errorCode.toString(), Toast.LENGTH_LONG)
                                                            .show();
                                                    try {
                                                        WsClient.sendWsEventLog(StagingActivity.this,
                                                                new HashMap<String, Object>() {{
                                                                    put("event_det", WsProtocol.EVENT.HT_STAGING_CHECKPOINT_FAILED);
                                                                    put("error_code", errorCode.getId());
                                                                    put("error_det", errorCode.getDet());
                                                                }}
                                                                , WsProtocol.EVENT.HT_UNLOCK_SCREEN_FAILED
                                                                , ProductionSchedule.STATUS.NG
                                                        );
                                                    } catch (Exception e) {
                                                        Log.e(getString(R.string.tag), e.getMessage());
                                                    }
                                                }
                                            }, screen_locked=true);
                                        }
                                }
                            }

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

            }
        });

    }

    @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())
        {
            if (popupLayout1.getVisibility() == VISIBLE) {
                Button btnOk = (Button) findViewById(R.id.popupLayout1_btn1);
                Button btnConfirm = (Button) findViewById(R.id.popupLayout1_btn2);
                switch (KeyMapping.fromId(keyCode)) {
                    case P1:
                        btnOk.performClick();
                        break;

                    case P2:
                        btnConfirm.performClick();
                        break;

                }
            } else {
                switch (KeyMapping.fromId(keyCode)) {
                    case P1:
                        btn_main_menu.performClick();
                        break;

                    case P2:
                        btn_clear.performClick();
                        break;

                    case P3:
                        btn_pending.performClick();
                        break;

                    case P4:
                        btn_ng.performClick();
                        break;

                }
            }
        } else if (keyCode == KeyMapping.ENT.getId()) {
            if (popupLayout2.getVisibility() == VISIBLE) {
                Button btn = (Button) findViewById(R.id.popupLayout2_btn1);
                btn.requestFocus();
                btn.performClick();
            }
            return false;
        }
        else if (keyCode >= 8 && keyCode <= 11) {
            if (!txt_qty.isFocused()
                && checkpoint != null) {
                checkpoint_check(String.valueOf(keyCode - 7));
            }
        }

        return super.onKeyUp(keyCode, event);
    }


    private void confirmation(String msg, int color, boolean isBtnOkShow
            , ActionListenerCallback callback, SpinAdapter spinAdapter) {


        Log.d(getString(R.string.tag), "confirmation() " + msg);

        RelativeLayout layout = popupLayout1;
        TextView lbl_msg = (TextView) findViewById(R.id.popupLayout1_txt);
        Button btnOk = (Button) findViewById(R.id.popupLayout1_btn1);
        Button btnConfirm = (Button) findViewById(R.id.popupLayout1_btn2);
        Spinner ddl_options = (Spinner) findViewById(R.id.ddl_options);

        ddl_options.setVisibility (spinAdapter == null ? GONE : VISIBLE);

        if (spinAdapter != null) {
            ddl_options.setAdapter(spinAdapter);
        }

        lbl_msg.setText(msg);
        lbl_msg.setTextColor(color);
        btnOk.setVisibility(isBtnOkShow ? VISIBLE : INVISIBLE);
        layout.setVisibility(VISIBLE);
        btnOk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    layout.setVisibility(GONE);
                    callback.onActionFailure(null);
                } catch (Exception e) {
                    // In case if item is the top most view
                };
            }
        });
        btnConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    layout.setVisibility(GONE);
                    callback.onActionSuccess(
                            spinAdapter.getItem(
                                    ddl_options.getSelectedItemPosition()
                            ).getName()
                    );
                } catch (Exception e) {
                    // In case if item is the top most view
                };
            }
        });

    }

    private void alertOk(String msg, ActionListenerCallback callback) {
        // Enable the ENT key down, it must current focus on multiline text input
        default_view.requestFocus();

        RelativeLayout layout = popupLayout2;
        TextView lbl_msg = (TextView) findViewById(R.id.popupLayout2_txt);
        Button btn = (Button) findViewById(R.id.popupLayout2_btn1);
        EditText txt_leader_password = (EditText) findViewById(R.id.txt_leader_password);
        txt_leader_password.setEnabled(false);

        lbl_msg.setText(msg);
        lbl_msg.setTextColor(getColor(R.color.black));
        layout.setVisibility(VISIBLE);
        txt_leader_password.setVisibility(GONE);
        btn.setBackgroundColor(getColor(R.color.green));
        btn.setTextColor(getColor(R.color.white));
        btn.setText("OK [ENT]");
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // stop activity
                try {
                    layout.setVisibility(GONE);
                    callback.onActionSuccess("");
                } catch (Exception e) {
                    // In case if item is the top most view
                };
            }
        });

    }

    private void alertError(String msg, ActionListenerCallback callback, Boolean isLockScreen) {
        alertError(msg, callback, isLockScreen, R.string.LEVEL_PERMIT_UNLOCK_SCREEN);
    }

    private void alertError(String msg, ActionListenerCallback callback, Boolean isLockScreen, int level_permit) {
        // Enable the ENT key down, it must current focus on multiline text input
        default_view.requestFocus();

        RelativeLayout layout = popupLayout2;
        TextView lbl_msg = (TextView) findViewById(R.id.popupLayout2_txt);
        Button btn = (Button) findViewById(R.id.popupLayout2_btn1);
        EditText txt_leader_password = (EditText) findViewById(R.id.txt_leader_password);
        txt_leader_password.setEnabled(false);

        if (isLockScreen) {
            txt_leader_password.setVisibility(VISIBLE);
            txt_leader_password.setText("");

            Utils.playMedia(getApplicationContext(), R.raw.ship_siren);
        } else {
            txt_leader_password.setVisibility(GONE);

            Utils.playTones(ToneGenerator.TONE_CDMA_ABBR_ALERT, 10000, 900);
        }

        lbl_msg.setText(msg);
        lbl_msg.setTextColor(getColor(R.color.red));
        layout.setVisibility(VISIBLE);
        btn.setBackgroundColor(getColor(R.color.red));
        btn.setTextColor(getColor(R.color.white));
        btn.setText("NG [" + (isLockScreen?"scan":"ENT") + "]");
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // stop activity
                try {
                    if (!isLockScreen) {
                        layout.setVisibility(GONE);
                        callback.onActionSuccess("");
                    } else {
                        // check password
                        if (!Settings.getMgmtList().containsKey(getString(level_permit))) {
                            callback.onActionFailure(new Exception(String.valueOf(E111.getId())));
                            return;
                        }

                        List<String> levelTokens = Arrays.asList(Settings.getMgmtList().get(getString(level_permit))
                                .split(getString(R.string.DELIMITER_SETTINGS)));
                        EditText txt_leader_password = (EditText) findViewById(R.id.txt_leader_password);
                        txt_leader_password.setEnabled(false);
                        if (!MainActivity.instance.userHashMap.containsKey(txt_leader_password.getText().toString())) {
                            callback.onActionFailure(new Exception(String.valueOf(E112.getId())));
                            return;
                        }

                        User user = MainActivity.instance.userHashMap.get(txt_leader_password.getText().toString());
                        if (levelTokens.contains(user.getLevel())) {
                            screen_locked = false;
                            layout.setVisibility(GONE);
                            callback.onActionSuccess("");
                        } else {
                            callback.onActionFailure(new Exception(String.valueOf(E122.getId())));
                        }
                    }



                } catch (Exception e) {
                    // In case if item is the top most view
                };
            }
        });

    }

    @Override
    public String getJobId() {
        return job_id;
    }

    @Override
    public String getStage() {
        return stage.toString();
    }

    @Override
    public void onBackPressed() {

    }
}