// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.android.impl.google.rpc.protocols.bt;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.util.Log;

import com.google.common.base.Splitter;

import org.joda.time.Duration;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;

import io.v.impl.google.rt.VRuntimeImpl;
import io.v.android.v23.V;
import io.v.v23.context.VContext;
import io.v.v23.rpc.Callback;
import io.v.v23.verror.VException;

/**
 * Handles bluetooth connection establishment on Android.
 * <p>
 * Used as a helper class for native code which sets up and registers the bluetooth protocol with
 * the vanadium RPC service.
 */
class Bluetooth {
    private static final String TAG = "Bluetooth";

    static Listener listen(VContext ctx, String btAddr) throws VException {
        String macAddr = getMACAddress(ctx, btAddr);
        int port = getPortNumber(btAddr);
        BluetoothServerSocket socket = listenOnPort(port);
        if (port == 0) {
            // listen on the first available port. Get the port number.
            port = getPortNumber(socket);
        }
        Log.d(TAG, String.format("listening on port %d", port));
        Executor executor = VRuntimeImpl.getRuntimeExecutor(ctx);
        if (executor == null) {
            throw new VException(
                    "NULL executor in context: did you derive this context from "
                            + "the context returned by V.init()?");
        }
        return new Listener(executor, socket, String.format("%s/%d", macAddr, port));
    }

    static void dial(
            VContext ctx, String btAddr, final Duration timeout, final Callback<Stream> callback)
            throws VException {
        final String macAddr = getMACAddress(ctx, btAddr);
        final int port = getPortNumber(btAddr);
        final Executor executor = VRuntimeImpl.getRuntimeExecutor(ctx);
        if (executor == null) {
            throw new VException(
                    "NULL executor in context: did you derive this context from "
                            + "the context returned by V.init()?");
        }
        executor.execute(
                new Runnable() {
                    @Override
                    public void run() {
                        final BluetoothDevice device =
                                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(macAddr);
                        try {
                            // Create a socket to the remote device.
                            // NOTE(spetrovic): Android's public methods currently only allow connection to
                            // a UUID, which goes through SDP.  Since we already have a remote port number,
                            // we connect to it directly, invoking a hidden method using reflection.
                            Method m =
                                    device.getClass()
                                            .getMethod(
                                                    "createInsecureRfcommSocket",
                                                    new Class[] {int.class});
                            final BluetoothSocket socket = (BluetoothSocket) m.invoke(device, port);
                            // Connect.
                            Timer timer = null;
                            if (timeout.getMillis() != 0) {
                                timer = new Timer();
                                timer.schedule(
                                        new TimerTask() {
                                            @Override
                                            public void run() {
                                                try {
                                                    socket.close();
                                                } catch (IOException e) {
                                                    System.err.println(
                                                            "Couldn't close BluetoothSocket.");
                                                }
                                            }
                                        },
                                        timeout.getMillis());
                            }
                            try {
                                socket.connect();
                            } catch (IOException e) {
                                socket.close();
                                callback.onFailure(
                                        new VException("Couldn't connect: " + e.getMessage()));
                            } finally {
                                if (timer != null) {
                                    timer.cancel();
                                }
                            }
                            // There is no way currently to retrieve the local port number for the
                            // connection, but that's probably OK.
                            String localAddr = String.format("%s/%d", localMACAddress(ctx), 0);
                            String remoteAddr = String.format("%s/%d", macAddr, port);
                            callback.onSuccess(new Stream(executor, socket, localAddr, remoteAddr));
                        } catch (Exception e) {
                            callback.onFailure(
                                    new VException(
                                            "Couldn't invoke createInsecureRfcommSocket: "
                                                    + e.getMessage()));
                        }
                    }
                });
    }

    private static BluetoothServerSocket listenOnPort(int port) throws VException {
        if (port == 0) {
            // Use SOCKET_CHANNEL_AUTO_STATIC (-2) to auto assign a channel number.
            port = -2;
        }
        // Use reflection to reach the hidden "listenUsingInsecureRfcommOn(port)" method.
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        try {
            Method m =
                    adapter.getClass()
                            .getMethod("listenUsingInsecureRfcommOn", new Class[] {int.class});
            return (BluetoothServerSocket) m.invoke(adapter, port);
        } catch (Exception e) {
            throw new VException("Error invoking listenUsingInsecureRfcommOn: " + e.getMessage());
        }
    }

    private static int getPortNumber(BluetoothServerSocket serverSocket) throws VException {
        // Use reflection to reach the hidden "getChannel()" method.
        try {
            Method m = serverSocket.getClass().getMethod("getChannel", new Class[0]);
            return (int) m.invoke(serverSocket);
        } catch (Exception e) {
            throw new VException("Error invoking getChannel: " + e.getMessage());
        }
    }

    private static String localMACAddress(VContext ctx) {
        // TODO(suharshs): Android has disallowed getting the local address.
        // This is a remaining working hack that gets the local bluetooth address,
        // just to get things working.
        return android.provider.Settings.Secure.getString(
                V.getAndroidContext(ctx).getContentResolver(), "bluetooth_address");
    }

    private static String getMACAddress(VContext ctx, String btAddr) throws VException {
        List<String> parts = Splitter.on("/").omitEmptyStrings().splitToList(btAddr);
        switch (parts.size()) {
            case 0:
                throw new VException(
                        String.format(
                                "Couldn't split bluetooth address \"%s\" using \"/\" separator: "
                                        + "got zero parts!",
                                btAddr));
            case 1:
                return localMACAddress(ctx);
            case 2:
                String address = parts.get(0).toUpperCase();
                if (!BluetoothAdapter.checkBluetoothAddress(address)) {
                    throw new VException("Invalid bluetooth address: " + btAddr);
                }
                return address;
            default:
                throw new VException(
                        String.format(
                                "Couldn't parse bluetooth address \"%s\": too many \"/\".",
                                btAddr));
        }
    }

    private static int getPortNumber(String btAddr) throws VException {
        List<String> parts = Splitter.on("/").splitToList(btAddr);
        switch (parts.size()) {
            case 0:
                throw new VException(
                        String.format(
                                "Couldn't split bluetooth address \"%s\" using \"/\" separator: "
                                        + "got zero parts!",
                                btAddr));
            case 1:
            case 2:
                try {
                    int port = Integer.parseInt((parts.get(parts.size() - 1)));
                    if (port < 0 || port > 32) {
                        throw new VException(
                                String.format(
                                        "Illegal port number %q in bluetooth " + "address \"%s\".",
                                        port, btAddr));
                    }
                    return port;
                } catch (NumberFormatException e) {
                    throw new VException(
                            String.format(
                                    "Couldn't parse port number in bluetooth address \"%s\": %s",
                                    btAddr, e.getMessage()));
                }
            default:
                throw new VException(
                        String.format(
                                "Couldn't parse bluetooth address \"%s\": too many \"/\".",
                                btAddr));
        }
    }

    static class Listener {
        private final Executor executor;
        private final BluetoothServerSocket serverSocket;
        private final String localAddress;

        Listener(Executor executor, BluetoothServerSocket serverSocket, String address) {
            this.executor = executor;
            this.serverSocket = serverSocket;
            this.localAddress = address;
        }

        void accept(final Callback<Stream> callback) {
            executor.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            try {
                                BluetoothSocket socket = serverSocket.accept();
                                // There is no way currently to retrieve the remote end's channel number,
                                // but that's probably OK.
                                String remoteAddress =
                                        String.format(
                                                "%s/%d", socket.getRemoteDevice().getAddress(), 0);
                                callback.onSuccess(
                                        new Stream(executor, socket, localAddress, remoteAddress));
                            } catch (IOException e) {
                                try {
                                    serverSocket.close();
                                } catch (IOException ioe) {
                                }
                                callback.onFailure(new VException(e.getMessage()));
                            }
                        }
                    });
        }

        void close() throws IOException {
            serverSocket.close();
        }

        String address() {
            return localAddress;
        }
    }

    static class Stream {
        private final Executor executor;
        private final BluetoothSocket socket;
        private final String localAddress;
        private final String remoteAddress;

        Stream(
                Executor executor,
                BluetoothSocket socket,
                String localAddress,
                String remoteAddress) {
            this.executor = executor;
            this.socket = socket;
            this.localAddress = localAddress;
            this.remoteAddress = remoteAddress;
        }

        void read(final int n, final Callback<byte[]> callback) {
            executor.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            try {
                                byte[] buf = new byte[n];
                                int num = socket.getInputStream().read(buf);
                                callback.onSuccess(
                                        num == buf.length ? buf : Arrays.copyOf(buf, num));
                            } catch (IOException e) {
                                try {
                                    socket.close();
                                } catch (IOException ioe) {
                                }
                                callback.onFailure(new VException(e.getMessage()));
                            }
                        }
                    });
        }

        void write(final byte[] data, final Callback<Void> callback) {
            executor.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            try {
                                socket.getOutputStream().write(data);
                                callback.onSuccess(null);
                            } catch (IOException e) {
                                try {
                                    socket.close();
                                } catch (IOException ioe) {
                                }
                                callback.onFailure(new VException(e.getMessage()));
                            }
                        }
                    });
        }

        void close() throws IOException {
            socket.close();
        }

        String localAddress() {
            return this.localAddress;
        }

        String remoteAddress() {
            return this.remoteAddress;
        }
    }

    private Bluetooth() {}
}
