package io.v.discoverysample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import io.v.android.libs.discovery.ble.BlePlugin;
import io.v.android.libs.security.BlessingsManager;
import io.v.android.v23.V;
import io.v.android.v23.services.blessing.BlessingCreationException;
import io.v.android.v23.services.blessing.BlessingService;
import io.v.impl.google.lib.discovery.UUIDUtil;
import io.v.v23.context.CancelableVContext;
import io.v.v23.context.VContext;
import io.v.v23.discovery.Attributes;
import io.v.v23.discovery.Service;
import io.v.v23.security.Blessings;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;
import io.v.x.ref.lib.discovery.Advertisement;
import io.v.x.ref.lib.discovery.EncryptionAlgorithm;


public class MainActivity extends Activity {

    private static final int BLESSINGS_REQUEST = 1;
    private Button chooseBlessingsButton;
    private Button scanButton;
    private Button advertiseButton;
    private Blessings blessings;
    private BlePlugin plugin;

    private VContext rootCtx;
    private CancelableVContext scanCtx;
    private CancelableVContext advCtx;

    private boolean isScanning;
    private boolean isAdvertising;

    private ScanHandlerAdapter adapter;

    private Advertisement advertisement;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        rootCtx = V.init(this);
        isScanning = false;
        isAdvertising = false;

        setContentView(R.layout.activity_main);
        chooseBlessingsButton = (Button)findViewById(R.id.blessingsButton);
        chooseBlessingsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fetchBlessings(false);
            }
        });

        scanButton = (Button)findViewById(R.id.scanForService);
        scanButton.setEnabled(false);
        scanButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                flipScan();
            }
        });

        advertiseButton = (Button) findViewById(R.id.advertiseButton);
        advertiseButton.setEnabled(false);
        advertiseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                flipAdvertise();
            }
        });

        byte[] instanceId = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15};
        Attributes attrs = new Attributes();
        attrs.put("foo", "bar");
        List<String> addrs = new ArrayList<>();
        addrs.add("localhost:2000");
        String interfaceName = "v.io/x/ref.Interface";
        advertisement = new Advertisement(
                new Service(instanceId, "Android instance",
                        interfaceName, attrs, addrs),
                UUIDUtil.UUIDtUuid(UUIDUtil.UUIDForInterfaceName(interfaceName)),
                new EncryptionAlgorithm(0),
                null,
                false);
        adapter = new ScanHandlerAdapter(this);
        ListView devices = (ListView) findViewById(R.id.list_view);
        devices.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    private void flipAdvertise() {
        if (plugin == null) {
            plugin = new BlePlugin(this);
        }

        if (!isAdvertising) {
            isAdvertising = true;

            advCtx = rootCtx.withCancel();
            try {
                plugin.addAdvertisement(advCtx, advertisement);
                advertiseButton.setText("Stop Advertisement");
            } catch (IOException e) {
                advCtx.cancel();
                isAdvertising = false;
            }
        } else {
            isAdvertising = false;
            advCtx.cancel();
            advertiseButton.setText("Advertise");
        }
    }
    private void flipScan() {
        if (plugin == null) {
            plugin = new BlePlugin(this);
        }
        if (!isScanning) {
            scanCtx = rootCtx.withCancel();
            plugin.addScanner(scanCtx,
                    UUIDUtil.UUIDForInterfaceName("v.io/x/ref.Interface"),
                    adapter);
            isScanning = true;
            scanButton.setText("Stop scanning");
        } else {
            isScanning = false;
            scanCtx.cancel();
            scanButton.setText("Start Scan");
        }
    }

    private void fetchBlessings(boolean startScan) {
        Intent intent = BlessingService.newBlessingIntent(this);
        startActivityForResult(intent, BLESSINGS_REQUEST);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case BLESSINGS_REQUEST:
                try {
                    // The Account Manager will pass us the blessings to use as
                    // an array of bytes. Use VomUtil to decode them...
                    byte[] blessingsVom =
                        BlessingService.extractBlessingReply(resultCode, data);
                    blessings = (Blessings) VomUtil.decode(blessingsVom, Blessings.class);
                    BlessingsManager.addBlessings(this, blessings);
                    Toast.makeText(this, "Success, ready to listen!",
                            Toast.LENGTH_SHORT).show();

                    // Enable the "start service" button.
                    scanButton.setEnabled(true);
                    advertiseButton.setEnabled(true);
                } catch (BlessingCreationException e) {
                    String msg = "Couldn't create blessing: " + e.getMessage();
                    Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
                } catch (VException e) {
                    String msg = "Couldn't store blessing: " + e.getMessage();
                    Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
                }
                return;
        }
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
