package com.shiitakeo.android_wear_for_ios;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.support.v4.app.NotificationCompat;
import android.support.wearable.activity.ConfirmationActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import android.view.View.OnClickListener;
import android.widget.TextView;

/**
 * Created by shiitakeo on 15/04/03.
 */
public class MusicControlActivity extends Activity {
    private static final String TAG_LOG = "BLE_wear";

    // BluetoothLeScanner does not work properly in my environment...
//    private int api_level = Build.VERSION.SDK_INT;
    private int api_level = 20;

    private BluetoothLeScanner le_scanner;
    private BluetoothAdapter bluetooth_adapter;
    private BluetoothGatt bluetooth_gatt;
    private BluetoothGattCharacteristic bluetooth_gatt_chara;
    private static Boolean is_connect = false;

    //ams Profile
    private static final String service_ams = "89d3502b-0f36-433a-8ef4-c502ad55f8dc";
    private static final String characteristics_remote_command = "9b3c81d8-57b1-4a8a-b8df-0e56f7ca51c2";
    private static final String characteristics_entity_update = "2f7cabce-808d-411f-9a0c-bb92ba96c102";
    private static final String descriptor_config = "00002902-0000-1000-8000-00805f9b34fb";

    String iphone_uuid = "";
    Boolean is_set_entity = false;
    private BroadcastReceiver message_receiver = new MessageReceiver();

    // intent action
    String set_artist_info = "com.shiitakeo.set_artist";
    String set_title_info = "com.shiitakeo.set_title";
    String extra_data = "com.shiitakeo.extra_data";



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

        Log.d(TAG_LOG, "-=-=-=-=-=-=-=-= onCreate @ MusicControlActivity -=-=-=-=-=-=-=-=-=");
        IntentFilter intent_filter = new IntentFilter();
        intent_filter.addAction(set_artist_info);
        intent_filter.addAction(set_title_info);
        registerReceiver(message_receiver, intent_filter);

        if(bluetooth_gatt != null) {
            bluetooth_gatt.disconnect();
            bluetooth_gatt.close();
            bluetooth_gatt = null;
        }
        if(bluetooth_adapter != null) {
            bluetooth_adapter = null;
        }
        if(api_level >= 21) {
            if (le_scanner != null) {
                Log.d(TAG_LOG, "status: ble reset");
                stop_le_scanner();
            }
        }
        is_connect = false;
        iphone_uuid = "";


        // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
        // BluetoothAdapter through BluetoothManager.
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        bluetooth_adapter = bluetoothManager.getAdapter();

        // Checks if Bluetooth is supported on the device.
        if (bluetooth_adapter == null) {
            Log.d(TAG_LOG, "ble adapter is null");
            return;
        }

        if(api_level >= 21) {
            Log.d(TAG_LOG, "start BLE scan @ lescan");
            start_le_scanner();
        }else {
            Log.d(TAG_LOG, "start BLE scan @ BluetoothAdapter");
            bluetooth_adapter.startLeScan(le_scan_callback);
        }
    }

    public void click_next_button(View view){
        Log.d(TAG_LOG, "-=-=-=-=-= next song -=-==-");
        bluetooth_gatt_chara.setValue(new byte[]{(byte) 0x03});
        bluetooth_gatt.writeCharacteristic(bluetooth_gatt_chara);

    }

    public void click_previous_button(View view){
        Log.d(TAG_LOG, "-=-=-=-=-= previous song -=-==-");
        bluetooth_gatt_chara.setValue(new byte[]{(byte) 0x04});
        bluetooth_gatt.writeCharacteristic(bluetooth_gatt_chara);

    }
    public void click_start_button(View view){
        Log.d(TAG_LOG, "-=-=-=-=-= start -=-==-");
        bluetooth_gatt_chara.setValue(new byte[]{(byte) 0x01});
        bluetooth_gatt.writeCharacteristic(bluetooth_gatt_chara);

    }

    public void click_stop_button(View view){
        Log.d(TAG_LOG, "-=-=-=-=-= stop -=-==-");
        bluetooth_gatt_chara.setValue(new byte[]{(byte) 0x02});
        bluetooth_gatt.writeCharacteristic(bluetooth_gatt_chara);

    }
    public void click_volume_up_button(View view){
        Log.d(TAG_LOG, "-=-=-=-=-= volume up -=-==-");
        bluetooth_gatt_chara.setValue(new byte[]{(byte) 0x05});
        bluetooth_gatt.writeCharacteristic(bluetooth_gatt_chara);

    }

    public void click_volume_down_button(View view){
        Log.d(TAG_LOG, "-=-=-=-=-= volume down -=-==-");
        bluetooth_gatt_chara.setValue(new byte[]{(byte) 0x06});
        bluetooth_gatt.writeCharacteristic(bluetooth_gatt_chara);

    }

    @TargetApi(21)
    private void start_le_scanner(){
        le_scanner = bluetooth_adapter.getBluetoothLeScanner();

//        ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).build();
//        le_scanner.startScan(scan_fillters(), settings, scan_callback);
//        le_scanner.startScan(scan_callback);
    }

    @TargetApi(21)
    private void stop_le_scanner(){
//        le_scanner.stopScan(scan_callback);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG_LOG, "~~~~~~~~ onDestroy @ Music Control Acitivity");
        if(api_level >= 21) {
            stop_le_scanner();
        }else {
            bluetooth_adapter.stopLeScan(le_scan_callback);
        }
        is_connect =false;
        iphone_uuid = "";

        if(null != bluetooth_gatt){
            bluetooth_gatt.disconnect();
            bluetooth_gatt.close();
            bluetooth_gatt = null;
        }
        bluetooth_adapter = null;
        super.onDestroy();
    }

    private List<ScanFilter> scan_fillters() {
        // can't find ancs service
        return create_scan_filter();
    }

    @TargetApi(21)
    private List<ScanFilter> create_scan_filter(){
//        ScanFilter filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(service_ancs)).build();
        ScanFilter filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(service_ams)).build();
        List<ScanFilter> list = new ArrayList<ScanFilter>(1);
        list.add(filter);
        return list;
    }


//    ScanCallback scan_callback = new ScanCallback() {

    @TargetApi(21)
    private class BLEScanCallback extends ScanCallback {
        @Override
        public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) {
            Log.d(TAG_LOG, "scan result" + result.toString());
//            Log.d(TAG_LOG, "device address" + result.getDevice().getAddress());
//            Log.d(TAG_LOG, "iphone address" + iphone_uuid);
//            Log.d(TAG_LOG, skip_count + "judge: " + result.getDevice().getAddress().toString().equals(iphone_uuid));
            BluetoothDevice device = result.getDevice();


        }


        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            Log.i(TAG_LOG, "batchscan result" + results.toString());
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.d(TAG_LOG, "onScanFailed" + errorCode);
        }
    }
//    };

    private BluetoothAdapter.LeScanCallback le_scan_callback = new BluetoothAdapter.LeScanCallback(){
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            Log.i(TAG_LOG, "onLeScan: " );

            if (!is_connect) {
                Log.d(TAG_LOG, "is connect");
                if (device != null) {
                    Log.d(TAG_LOG, "device ");
                    if (device.getName() != null) {
//                        if(device.getName().equals("Blank")) {
                        if(device.getName().equals("BLE Utility")) {
                            Log.d(TAG_LOG, "getname: " + device.getName());
                            iphone_uuid = device.getAddress().toString();
                            is_connect = true;
                            bluetooth_gatt = device.connectGatt(getApplicationContext(), false, bluetooth_gattCallback);
                            bluetooth_adapter.stopLeScan(le_scan_callback);
                        }
                    }
                }
            }


        }
    };

    private final BluetoothGattCallback bluetooth_gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.d(TAG_LOG, "onConnectionStateChange: " + status + " -> " + newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                // success, connect to gatt.
                // find service
                gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d(TAG_LOG, "onDisconnect: ");

            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.d(TAG_LOG, "onServicesDiscovered received: " + status);

            if (status == BluetoothGatt.GATT_SUCCESS) {
                if(!is_set_entity){
                bluetooth_gatt = gatt;

                // for ams
                BluetoothGattService service = gatt.getService(UUID.fromString(service_ams));
                BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characteristics_remote_command));

                if (characteristic == null) {
                    Log.d(TAG_LOG, " cant find chara");
                } else {
                    Log.d(TAG_LOG, " ** find chara :: " + characteristic.getUuid());
//                    if ("0001".equals(characteristic.getUuid().toString())) {
                    Log.d(TAG_LOG, " set notify:: " + characteristic.getUuid());
                    bluetooth_gatt_chara = characteristic;

                    request_media_info();
                }
            }else {
                try {
                    Log.d(TAG_LOG, "-=-=-=-=- set request -=-=-==-=-=-=");
                    BluetoothGattService service = bluetooth_gatt.getService(UUID.fromString(service_ams));
                    if(service != null) {
                        BluetoothGattCharacteristic chara = service.getCharacteristic(UUID.fromString(characteristics_entity_update));
                        if(chara != null) {
                            bluetooth_gatt.setCharacteristicNotification(chara, true);
                            BluetoothGattDescriptor desc = chara.getDescriptor(UUID.fromString(descriptor_config));
                            if(desc != null) {
                                desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                bluetooth_gatt.writeDescriptor(desc);
                            }
                        }
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
            }
        }

        private void request_media_info(){
            is_set_entity = true;
            bluetooth_gatt.discoverServices();
            Log.d(TAG_LOG, "request media info");
        }


        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            Log.d(TAG_LOG, " onDescriptorWrite:: " + status);
            // Notification source
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG_LOG, "status: write success ");
                //find music controll service
                Log.d(TAG_LOG, "*+*+*+*+*+*+*+*+*+*+ find music control");
                BluetoothGattService service = bluetooth_gatt.getService(UUID.fromString(service_ams));
                if(service != null) {
                    BluetoothGattCharacteristic chara = service.getCharacteristic(UUID.fromString(characteristics_entity_update));
                    if(chara != null) {
                        chara.setValue(new byte[]{(byte) 0x02, (byte) 0x00, (byte) 0x02});
                        bluetooth_gatt.writeCharacteristic(chara);
                    }
                }
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            Log.d(TAG_LOG, "onCharacteristicRead:: " + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG_LOG, "+onCharacteristicRead:: " + status);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            Log.d(TAG_LOG, "onCharacteristicChanged:: " + characteristic.getUuid().toString());

            if (characteristics_entity_update.toString().equals(characteristic.getUuid().toString())) {
                Log.d(TAG_LOG, "entity update ");

                byte[] get_data = characteristic.getValue();
                String str = characteristic.getStringValue(3);
                Log.d(TAG_LOG, "new music info: " + str);

                if(get_data[1] == (byte)0x00) {
                    Log.d(TAG_LOG, "get artist info");

                    Intent _intent_positive = new Intent();
                    _intent_positive.setAction(set_artist_info);
                    _intent_positive.putExtra(extra_data, str);
                    sendBroadcast(_intent_positive);
                }else if(get_data[1] == (byte)0x02) {
                    Log.d(TAG_LOG, "get title info");

                    Intent _intent_positive = new Intent();
                    _intent_positive.setAction(set_title_info);
                    _intent_positive.putExtra(extra_data, str);
                    sendBroadcast(_intent_positive);
                }
            }
        }
    };

    @TargetApi(20)
    public class MessageReceiver extends BroadcastReceiver {
        private static final String TAG_LOG = "BLE_wear";

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG_LOG, "onReceive");
            String action = intent.getAction();

            // perform notification action: immediately
            // delete intent: after 7~8sec.
            if (action.equals(set_artist_info)) {
                Log.d(TAG_LOG, "get action: " + action);

                String str = intent.getStringExtra(extra_data);
                Log.d(TAG_LOG, "get artist info: " + str);

                TextView textView = (TextView) findViewById(R.id.text_artist);
                textView.setText(str);
            }else if (action.equals(set_title_info)) {
                Log.d(TAG_LOG, "get action: " + action);

                String str = intent.getStringExtra(extra_data);
                Log.d(TAG_LOG, "get title info: " + str);

                TextView textView = (TextView) findViewById(R.id.text_title);
                textView.setText(str);
            }
        }
    }
}