// Copyright 2016 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.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import io.v.android.v23.V;
import io.v.v23.context.VContext;

/**
 * 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.
 */
public class BluetoothWithSdp {
    private static final String TAG = "Bluetooth";

    private static final String SDP_NAME = "v23";
    // Generated by UUID5(UUID5(NULL, "v.io"), "_bluetooth_socket_port")
    private static final UUID BASE_SDP_UUID =
            UUID.fromString("0f83a207-7f39-57c4-92f6-bd46039a5540");

    private static final int MAX_PORT = 30;
    private static final int PORT_MASK = 0x31;

    private static final List<Integer> sPorts;

    static {
        sPorts = new ArrayList<>();
        for (int i = 1; i <= MAX_PORT; i++) {
            sPorts.add(i);
        }
        // Shuffle port numbers to prevent peers from using cached SDP records.
        Collections.shuffle(sPorts, new Random(System.currentTimeMillis()));
    }

    private static synchronized int getServerPort(int port) throws IOException {
        if (port == 0) {
            if (sPorts.isEmpty()) {
                throw new IOException("No more ports available");
            }
            port = sPorts.get(0);
        }
        if (!sPorts.remove(new Integer(port))) {
            throw new IOException(String.format("Port %d not available", port));
        }
        return port;
    }

    private static synchronized void putServerPort(int port) {
        if (port > 0 && port <= MAX_PORT && !sPorts.contains(port)) {
            sPorts.add(port);
        }
    }

    private static UUID getSdpUuidFromPort(int port) {
        if (port <= 0 || port > MAX_PORT) {
            throw new IllegalArgumentException(String.format("Illegal port number %d", port));
        }
        return new UUID(
                BASE_SDP_UUID.getMostSignificantBits(),
                BASE_SDP_UUID.getLeastSignificantBits() | (long) port);
    }

    private static String getLocalMacAddress(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 address) {
        List<String> parts = Splitter.on("/").omitEmptyStrings().splitToList(address);
        switch (parts.size()) {
            case 0:
                throw new IllegalArgumentException(
                        String.format(
                                "Couldn't split bluetooth address \"%s\" using \"/\" separator: "
                                        + "got zero parts!",
                                address));
            case 1:
                return getLocalMacAddress(ctx);
            case 2:
                String macAddress = parts.get(0).toUpperCase();
                if (!BluetoothAdapter.checkBluetoothAddress(macAddress)) {
                    throw new IllegalArgumentException("Invalid bluetooth address: " + address);
                }
                return macAddress;
            default:
                throw new IllegalArgumentException(
                        String.format(
                                "Couldn't parse bluetooth address \"%s\": too many \"/\".",
                                address));
        }
    }

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

    static Listener listen(VContext ctx, String address) throws Exception {
        String macAddress = getMacAddress(ctx, address);
        int port = getPortNumber(address);
        return new Listener(macAddress, port);
    }

    static Stream dial(VContext ctx, String address, Duration timeout) throws Exception {
        String macAddress = getMacAddress(ctx, address);
        int port = getPortNumber(address);

        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            throw new IOException("BluetoothAdapter not available");
        }
        BluetoothDevice device = adapter.getRemoteDevice(macAddress);

        UUID uuid = getSdpUuidFromPort(port);
        final BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid);

        Timer timer = null;
        if (timeout.getMillis() != 0) {
            timer = new Timer();
            timer.schedule(
                    new TimerTask() {
                        @Override
                        public void run() {
                            try {
                                socket.close();
                            } catch (IOException e) {
                            }
                        }
                    },
                    timeout.getMillis());
        }

        try {
            socket.connect();
        } catch (IOException e) {
            socket.close();
            throw e;
        } 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 localAddress = String.format("%s/0", getLocalMacAddress(ctx));
        String remoteAddress = String.format("%s/%d", macAddress, port);
        return new Stream(socket, localAddress, remoteAddress);
    }

    // Listener provides methods for accepting new Bluetooth connections.
    public static class Listener {
        private final String mLocalAddress;

        private int mPort;
        private BluetoothServerSocket mServerSocket;

        private Listener(String macAddress, int port) throws IOException {
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
            if (adapter == null) {
                throw new IOException("BluetoothAdapter not available");
            }

            mPort = getServerPort(port);
            mLocalAddress = String.format("%s/%d", macAddress, mPort);

            Log.d(TAG, String.format("listening on port %d", mPort));

            try {
                UUID uuid = getSdpUuidFromPort(mPort);
                mServerSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(SDP_NAME, uuid);
            } catch (IOException e) {
                close();
                throw e;
            }
        }

        public Stream accept() throws IOException {
            //  Android developer guide says that unlike TCP/IP, RFCOMM only allows one connected client per
            //  channel at a time: https://developer.android.com/guide/topics/connectivity/bluetooth.html.
            //
            //  TODO(jhahn,suharshs): Is this true?
            try {
                BluetoothSocket socket = mServerSocket.accept();
                // There is no way currently to retrieve the remote end's channel number,
                // but that's probably OK.
                String remoteAddress = String.format("%s/0", socket.getRemoteDevice().getAddress());
                return new Stream(socket, mLocalAddress, remoteAddress);
            } catch (IOException e) {
                close();
                throw e;
            }
        }

        public synchronized void close() throws IOException {
            if (mPort > 0) {
                putServerPort(mPort);
                mPort = 0;
            }
            if (mServerSocket != null) {
                mServerSocket.close();
                mServerSocket = null;
            }
        }

        public String address() {
            return mLocalAddress;
        }

        protected void finalize() {
            try {
                close();
            } catch (IOException e) {
            }
        }
    }

    // Stream provides I/O primitives to read and write over a Bluetooth socket.
    public static class Stream {
        private final BluetoothSocket mSocket;
        private final String mLocalAddress;
        private final String mRemoteAddress;

        private Stream(BluetoothSocket socket, String localAddress, String remoteAddress) {
            mSocket = socket;
            mLocalAddress = localAddress;
            mRemoteAddress = remoteAddress;
        }

        public byte[] read(int n) throws IOException {
            try {
                InputStream in = mSocket.getInputStream();
                byte[] buf = new byte[n];
                int total = 0;
                while (total < n) {
                    int r = in.read(buf, total, n - total);
                    if (r < 0) {
                        break;
                    }
                    total += r;
                }
                return total == n ? buf : Arrays.copyOf(buf, total);
            } catch (IOException e) {
                close();
                throw e;
            }
        }

        public void write(byte[] data) throws IOException {
            try {
                // TODO(jhahn): Do we need to flush for every write?
                OutputStream out = mSocket.getOutputStream();
                out.write(data);
            } catch (IOException e) {
                close();
                throw e;
            }
        }

        public void close() throws IOException {
            mSocket.close();
        }

        public String localAddress() {
            return mLocalAddress;
        }

        public String remoteAddress() {
            return mRemoteAddress;
        }
    }
}
