package com.ivrjack.ru01.demo;

import android.Manifest;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.ivrjack.ru01.IvrJackAdapter;
import com.ivrjack.ru01.IvrJackService;
import com.ivrjack.ru01.IvrJackStatus;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class MainActivity extends ListActivity implements IvrJackAdapter {

    private static final String TAG = "ru01";
    private static final int REQUEST_FOR_PERMISSION = 1;

    public static IvrJackService service;

    private TextView viewStatus;
    private TextView viewTime;
    private ImageView viewProgress;
    private View layoutReader;
    private View viewPlugout;
    private Button buttonStart;
    private Button buttonClear;
    private Button buttonSingle;
    private TextView viewTotal;
    private ImageButton buttonSetting;
    private ProgressBar viewVolume;

    private EpcAdapter adapter;
    private MainHandler handler;

    private Thread testReportThread;

    private BroadcastReceiver volumeBroadcast;

    @Override
    public void onConnect(String deviceSn) {
        Log.i(TAG, "on connect");
        viewPlugout.setVisibility(View.GONE);
        layoutReader.setVisibility(View.VISIBLE);
    }

    @Override
    public void onDisconnect() {
        Log.i(TAG, "on disconnect");
        layoutReader.setVisibility(View.GONE);
        viewPlugout.setVisibility(View.VISIBLE);
    }

    @Override
    public void onStatusChange(IvrJackStatus status) {
        Log.i(TAG, "on status change: " + status);
        switch (status) {
            case ijsDetecting:
                viewStatus.setText("Device detecting...");
                startAnimation();
                AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                viewVolume.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
                viewVolume.setProgress(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
                if (viewVolume.getMax() != viewVolume.getProgress()) {
                    new AlertDialog.Builder(this)
                            .setTitle("Please set the volume to maximum!")
                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                }
                            }).show();
                }
                break;
            case ijsRecognized:
                viewStatus.setText("Device connected.");
                stopAnimation();
                sendTestReport(true);
                break;
            case ijsUnRecognized:
                viewStatus.setText("Device unrecognized.");
                stopAnimation();
                sendTestReport(false);
                break;
            case ijsPlugout:
                viewStatus.setText("Device disconnected.");
                stopAnimation();
                break;
        }
    }

    @Override
    public void onInventory(byte[] epc, double rssi) {

        StringBuilder builder = new StringBuilder();
        for (int i=0; i<epc.length; i++) {
            builder.append(String.format("%02X", epc[i]));
            if ((i+1)%4==0) builder.append(" ");
        }
        adapter.addEpcRecord(builder.toString(), rssi);
        final int total = adapter.getTotal();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                viewTotal.setText("Total: " + total);
            }
        });
    }



    public void onStart(View v) {
        if (buttonStart.getText().toString().equals(">>>Start<<<")) {
            startAnimation();
            buttonStart.setEnabled(false);
            buttonSetting.setEnabled(false);
            new Thread(new StartTask()).start();
        } else {
            startAnimation();
            buttonStart.setEnabled(false);
            new Thread(new StopTask()).start();
        }
    }

    public void onInventory(View v){
        Log.i("inventory", "onInventory: ");
        buttonSingle.setEnabled(false);
        buttonStart.setEnabled(false);
        buttonSetting.setEnabled(false);
        new Thread(new InventoryTask()).start();
    }

    public void onTamper(View v) {
        if (buttonStart.getText().toString().equals(">>>Start<<<")) {
            startActivity(new Intent(this, TagScanActivity.class));
        }
    }

    public void onClear(View v) {
        adapter.clearEpcRecords();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                viewTotal.setText("Total: 0");
            }
        });
    }

    public void onSetting(View v) {
        if (buttonStart.getText().toString().equals(">>>Start<<<")) {
            startActivity(new Intent(this, SettingsActivity.class));
        }
    }

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

        viewStatus = (TextView) findViewById(R.id.status);
        viewTime = (TextView) findViewById(R.id.time);
        viewProgress = (ImageView) findViewById(R.id.progress);
        layoutReader = findViewById(R.id.reader);
        viewPlugout = findViewById(R.id.plugout);
        viewVolume = (ProgressBar) findViewById(R.id.volume);
        viewTotal = (TextView) findViewById(R.id.total);

        buttonStart = (Button) findViewById(R.id.start);
        buttonClear = (Button) findViewById(R.id.clear);
        buttonSingle = (Button) findViewById(R.id.single);
        buttonSetting = (ImageButton) findViewById(R.id.settings);

        viewTime.setText(new SimpleDateFormat("yyyy-MM-dd E", Locale.US).format(new Date()));

        adapter = new EpcAdapter(this);
        setListAdapter(adapter);

        handler = new MainHandler(this);

        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        viewVolume.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
        viewVolume.setProgress(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
        volumeBroadcast = new VolumnBroadcast();
        registerReceiver(volumeBroadcast, new IntentFilter("android.media.VOLUME_CHANGED_ACTION"));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (this.checkSelfPermission(Manifest.permission.RECORD_AUDIO) !=
                    PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[] {Manifest.permission.RECORD_AUDIO},
                        REQUEST_FOR_PERMISSION);
            } else {
                service = new IvrJackService(this, this, 1);
                service.open();
            }
        } else {
            service = new IvrJackService(this, this, 1);
            service.open();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_FOR_PERMISSION: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    service = new IvrJackService(this, this, 1);
                    service.open();
                } else {
                    Toast.makeText(this, "audio record perssion denied.", Toast.LENGTH_LONG).show();
                    finish();
                }
                return;
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onDestroy() {
        service.close();
        service = null;

        unregisterReceiver(volumeBroadcast);
        super.onDestroy();
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        if (buttonStart.getText().toString().equals(">>>Start<<<"))
        {
            EpcRecord epc = (EpcRecord) adapter.getItem(position);
            Intent intent = new Intent(this, TagActivity.class);
            intent.putExtra("epc", epc.epc);
            startActivity(intent);
        }
    }

    private void startAnimation() {
        viewProgress.setVisibility(View.VISIBLE);
        AnimationDrawable anim = (AnimationDrawable) viewProgress.getDrawable();
        anim.start();
    }

    private void stopAnimation() {
        viewProgress.setVisibility(View.INVISIBLE);
        AnimationDrawable anim = (AnimationDrawable) viewProgress.getDrawable();
        anim.stop();
    }

    private void sendTestReport(final boolean connectResult) {
        // 检查是否已经发送过测试报告
        final SharedPreferences sp = getSharedPreferences("ru01", 0);
        boolean flag = sp.getBoolean("TestReportFlag", false);
        if (flag) {
            boolean result = sp.getBoolean("TestReportResult", false);
            if (result || !connectResult) return;
        }

        // 检查是否正在发送测试报告
        if (testReportThread != null && testReportThread.isAlive()) return;

        // 开启后台线程发送测试报告
        testReportThread = new Thread() {
            @Override
            public void run() {
                SharedPreferences.Editor editor = sp.edit();
                if (service.sendTestReport()) {
                    // 发送成功，保存flag
                    editor.putBoolean("TestReportFlag", true);
                    editor.putBoolean("TestReportResult", connectResult);
                    editor.commit();
                    Log.i("ru01", "send test report success");
                }
            }
        };
        testReportThread.start();
    }

    static class EpcAdapter extends BaseAdapter {

        LayoutInflater inflater;
        List<EpcRecord> epcs;

        public EpcAdapter(Context context) {
            inflater = LayoutInflater.from(context);
            epcs = new ArrayList<EpcRecord>();
        }

        public void addEpcRecord(String epc, double rssi) {
            EpcRecord epcRecord = null;
            for (EpcRecord er : epcs) {
                if (er.epc.equals(epc)) {
                    epcRecord = er;
                    break;
                }
            }
            if (epcRecord != null) {
                epcRecord.count++;
                epcRecord.rssi = String.valueOf(rssi);
            } else {
                epcs.add(new EpcRecord(epcs.size() + 1, epc, String.valueOf(rssi),1));
            }
            notifyDataSetInvalidated();
        }

        public void clearEpcRecords() {
            epcs.clear();
            notifyDataSetInvalidated();
        }

        public int getTotal() {
            int total = 0;
            for (EpcRecord epc : epcs) {
                total += epc.count;
            }
            return total;
        }

        @Override
        public int getCount() {
            return epcs.size();
        }

        @Override
        public Object getItem(int position) {
            return epcs.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                view = inflater.inflate(R.layout.epc_item, null);
            }
            EpcRecord epc = epcs.get(position);
            ((TextView) view.findViewById(R.id.no)).setText(String.valueOf(epc.no));
            ((TextView) view.findViewById(R.id.epc)).setText(epc.epc);
            ((TextView)view.findViewById(R.id.rssi)).setText(epc.rssi);
            ((TextView) view.findViewById(R.id.count)).setText(String.valueOf(epc.count));
            return view;
        }
    }

    class StartTask implements Runnable {

        @Override
        public void run() {
            int ret = service.setReadEpcStatus((byte) 1);
            handler.obtainMessage(0, ret).sendToTarget();
        }
    }

    class StopTask implements Runnable {

        @Override
        public void run() {
            int ret = service.setReadEpcStatus((byte) 0);
            handler.obtainMessage(1, ret).sendToTarget();
        }
    }

    class InventoryTask implements Runnable{
        @Override
        public void run() {
            final List<IvrJackService.TagEpcAndRssi> tags = new ArrayList<>();
            final int ret = service.inventory(tags);
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    if(ret == 0){
                        Log.i("inventory", "inventory success");
                        for(IvrJackService.TagEpcAndRssi tag : tags){
                            onInventory(tag.epc, tag.rssi);
                        }
                    }else if(ret == IvrJackService.ERROR_INVENTORY_NOTAG) {
                        Log.i("inventory", "no tag");
                        handler.obtainMessage(2, ret).sendToTarget();
                    }else{
                        Log.i("inventory", "inventory fail");
                        handler.obtainMessage(3, ret).sendToTarget();
                    }
                    buttonSingle.setEnabled(true);
                    buttonSetting.setEnabled(true);
                    buttonStart.setEnabled(true);
                }
            });
        }
    }

    class MainHandler extends Handler {
        private Context mContext;

        public MainHandler(Context context) {
            super(Looper.getMainLooper());
            mContext = context;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0: {
                    stopAnimation();
                    int ret = (Integer) msg.obj;
                    if (ret == 0) {
                        buttonStart.setText(">>>Stop<<<");
                        viewStatus.setText("Device start read epc");
                        buttonSingle.setVisibility(View.INVISIBLE);
                    } else {
                        viewStatus.setText("Device start read epc failed: " + ret);
                        buttonSetting.setEnabled(true);
                    }
                    buttonStart.setEnabled(true);
                    break;
                }
                case 1: {
                    stopAnimation();
                    buttonStart.setEnabled(true);
                    buttonSetting.setEnabled(true);
                    buttonStart.setText(">>>Start<<<");
                    viewStatus.setText("Device stop read epc");
                    buttonSingle.setVisibility(View.VISIBLE);
                    break;
                }
                case 2:{
                    Toast.makeText(mContext, "No Tag!", Toast.LENGTH_SHORT).show();
                    break;
                }
                case 3:{
                    Toast.makeText(mContext, "Inventory failed!", Toast.LENGTH_SHORT).show();
                    break;
                }
                default:
                    break;
            }
        }
    }

    private class VolumnBroadcast extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            viewVolume.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
            viewVolume.setProgress(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
        }

    }

}
