/*
 * Copyright (C) 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.googlecode.android_scripting.facade.bluetooth;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.IntentFilter;
import android.os.ParcelFileDescriptor;

import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcDefault;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.lang.reflect.Field;

import org.apache.commons.codec.binary.Base64Codec;

/**
 * Bluetooth functions.
 *
 */
// Discovery functions added by Eden Sayag

public class BluetoothRfcommFacade extends RpcReceiver {

  // UUID for SL4A.
  private static final String DEFAULT_UUID = "457807c0-4897-11df-9879-0800200c9a66";
  private static final String SDP_NAME = "SL4A";
  private final Service mService;
  private final BluetoothPairingHelper mPairingReceiver;
  private final BluetoothAdapter mBluetoothAdapter;
  private Map<String, BluetoothConnection>
          connections = new HashMap<String, BluetoothConnection>();

  public BluetoothRfcommFacade(FacadeManager manager) {
    super(manager);
    mService = manager.getService();
    mPairingReceiver = new BluetoothPairingHelper();
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  }

  private BluetoothConnection getConnection(String connID) throws IOException {
    BluetoothConnection conn = null;
    if (connID.trim().length() > 0) {
      conn = connections.get(connID);
    } else if (connections.size() == 1) {
      conn = (BluetoothConnection) connections.values().toArray()[0];
    }
    if (conn == null) {
      throw new IOException("Bluetooth not ready for this connID.");
    }
    return conn;
  }

  private String addConnection(BluetoothConnection conn) {
    String uuid = UUID.randomUUID().toString();
    connections.put(uuid, conn);
    conn.setUUID(uuid);
    return uuid;
  }

  @Rpc(description = "Connect to a device over Bluetooth. "
                   + "Blocks until the connection is established or fails.",
       returns = "True if the connection was established successfully.")
  public String bluetoothRfcommConnect(
      @RpcParameter(name = "address", description = "The mac address of the device to connect to.")
      String address,
      @RpcParameter(name = "uuid",
      description = "The UUID passed here must match the UUID used by the server device.")
      @RpcDefault(DEFAULT_UUID)
      String uuid)
      throws IOException {
    BluetoothDevice mDevice;
    BluetoothSocket mSocket;
    BluetoothConnection conn;
    mDevice = mBluetoothAdapter.getRemoteDevice(address);
    mSocket = mDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));

    // Register a broadcast receiver to bypass manual confirmation
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
    mService.registerReceiver(mPairingReceiver, filter);

    // Always cancel discovery because it will slow down a connection.
    mBluetoothAdapter.cancelDiscovery();
    mSocket.connect();
    conn = new BluetoothConnection(mSocket);

    mService.unregisterReceiver(mPairingReceiver);
    return addConnection(conn);
  }

  @Rpc(description = "Returns active Bluetooth connections.")
  public Map<String, String> bluetoothRfcommActiveConnections() {
    Map<String, String> out = new HashMap<String, String>();
    for (Map.Entry<String, BluetoothConnection> entry : connections.entrySet()) {
      if (entry.getValue().isConnected()) {
        out.put(entry.getKey(), entry.getValue().getRemoteBluetoothAddress());
      }
    }
    return out;
  }

  @Rpc(description = "Returns the name of the connected device.")
  public String bluetoothRfcommGetConnectedDeviceName(
      @RpcParameter(name = "connID", description = "Connection id")
      @RpcOptional @RpcDefault("")
      String connID)
      throws IOException {
    BluetoothConnection conn = getConnection(connID);
    return conn.getConnectedDeviceName();
  }

  @Rpc(description = "Listens for and accepts a Bluetooth connection."
                   + "Blocks until the connection is established or fails.")
  public String bluetoothRfcommAccept(
      @RpcParameter(name = "uuid") @RpcDefault(DEFAULT_UUID) String uuid,
      @RpcParameter(name = "timeout",
                    description = "How long to wait for a new connection, 0 is wait for ever")
      @RpcDefault("0") Integer timeout)
      throws IOException {
    Log.d("Accept bluetooth connection");
    BluetoothServerSocket mServerSocket;
    mServerSocket =
        mBluetoothAdapter.listenUsingRfcommWithServiceRecord(SDP_NAME, UUID.fromString(uuid));
    // Register a broadcast receiver to bypass manual confirmation
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
    mService.registerReceiver(mPairingReceiver, filter);

    BluetoothSocket mSocket = mServerSocket.accept(timeout.intValue());
    BluetoothConnection conn = new BluetoothConnection(mSocket, mServerSocket);
    mService.unregisterReceiver(mPairingReceiver);
    return addConnection(conn);
  }

  @Rpc(description = "Sends ASCII characters over the currently open Bluetooth connection.")
  public void bluetoothRfcommWrite(@RpcParameter(name = "ascii") String ascii,
      @RpcParameter(name = "connID", description = "Connection id") @RpcDefault("") String connID)
      throws IOException {
    BluetoothConnection conn = getConnection(connID);
    try {
      conn.write(ascii);
    } catch (IOException e) {
      connections.remove(conn.getUUID());
      throw e;
    }
  }

  @Rpc(description = "Read up to bufferSize ASCII characters.")
  public String bluetoothRfcommRead(
      @RpcParameter(name = "bufferSize") @RpcDefault("4096") Integer bufferSize,
      @RpcParameter(name = "connID", description = "Connection id") @RpcOptional @RpcDefault("")
      String connID)
      throws IOException {
    BluetoothConnection conn = getConnection(connID);
    try {
      return conn.read(bufferSize);
    } catch (IOException e) {
      connections.remove(conn.getUUID());
      throw e;
    }
  }

  @Rpc(description = "Send bytes over the currently open Bluetooth connection.")
  public void bluetoothRfcommWriteBinary(
      @RpcParameter(name = "base64",
                    description = "A base64 encoded String of the bytes to be sent.")
      String base64,
      @RpcParameter(name = "connID", description = "Connection id")
      @RpcDefault("") @RpcOptional
      String connID)
      throws IOException {
    BluetoothConnection conn = getConnection(connID);
    try {
      conn.write(Base64Codec.decodeBase64(base64));
    } catch (IOException e) {
      connections.remove(conn.getUUID());
      throw e;
    }
  }

  @Rpc(description = "Read up to bufferSize bytes and return a chunked, base64 encoded string.")
  public String bluetoothRfcommReadBinary(
      @RpcParameter(name = "bufferSize") @RpcDefault("4096") Integer bufferSize,
      @RpcParameter(name = "connID", description = "Connection id")
      @RpcDefault("") @RpcOptional
      String connID)
      throws IOException {

    BluetoothConnection conn = getConnection(connID);
    try {
      return Base64Codec.encodeBase64String(conn.readBinary(bufferSize));
    } catch (IOException e) {
      connections.remove(conn.getUUID());
      throw e;
    }
  }

  @Rpc(description = "Returns True if the next read is guaranteed not to block.")
  public Boolean bluetoothRfcommReadReady(
      @RpcParameter(name = "connID", description = "Connection id") @RpcDefault("") @RpcOptional
      String connID)
      throws IOException {
    BluetoothConnection conn = getConnection(connID);
    try {
      return conn.readReady();
    } catch (IOException e) {
      connections.remove(conn.getUUID());
      throw e;
    }
  }

  @Rpc(description = "Read the next line.")
  public String bluetoothRfcommReadLine(
      @RpcParameter(name = "connID", description = "Connection id") @RpcOptional @RpcDefault("")
      String connID)
      throws IOException {
    BluetoothConnection conn = getConnection(connID);
    try {
      return conn.readLine();
    } catch (IOException e) {
      connections.remove(conn.getUUID());
      throw e;
    }
  }

  @Rpc(description = "Stops Bluetooth connection.")
  public void bluetoothRfcommStop(
      @RpcParameter
      (name = "connID", description = "Connection id") @RpcOptional @RpcDefault("")
      String connID) {
    BluetoothConnection conn;
    try {
      conn = getConnection(connID);
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }
    if (conn == null) {
      return;
    }

    conn.stop();
    connections.remove(conn.getUUID());
  }

  @Override
  public void shutdown() {
    for (Map.Entry<String, BluetoothConnection> entry : connections.entrySet()) {
      entry.getValue().stop();
    }
    connections.clear();
  }
}

class BluetoothConnection {
  private BluetoothSocket mSocket;
  private BluetoothDevice mDevice;
  private OutputStream mOutputStream;
  private InputStream mInputStream;
  private BufferedReader mReader;
  private BluetoothServerSocket mServerSocket;
  private String UUID;

  public BluetoothConnection(BluetoothSocket mSocket) throws IOException {
    this(mSocket, null);
  }

  public BluetoothConnection(BluetoothSocket mSocket, BluetoothServerSocket mServerSocket)
      throws IOException {
    this.mSocket = mSocket;
    mOutputStream = mSocket.getOutputStream();
    mInputStream = mSocket.getInputStream();
    mDevice = mSocket.getRemoteDevice();
    mReader = new BufferedReader(new InputStreamReader(mInputStream, "ASCII"));
    this.mServerSocket = mServerSocket;
  }

  public void setUUID(String UUID) {
    this.UUID = UUID;
  }

  public String getUUID() {
    return UUID;
  }

  public String getRemoteBluetoothAddress() {
    return mDevice.getAddress();
  }

  public boolean isConnected() {
    if (mSocket == null) {
      return false;
    }
    try {
      mSocket.getRemoteDevice();
      mInputStream.available();
      mReader.ready();
      return true;
    } catch (Exception e) {
      return false;
    }
  }

  public void write(byte[] out) throws IOException {
    if (mOutputStream != null) {
      mOutputStream.write(out);
    } else {
      throw new IOException("Bluetooth not ready.");
    }
  }

  public void write(String out) throws IOException {
    this.write(out.getBytes());
  }

  public Boolean readReady() throws IOException {
    if (mReader != null) {
      return mReader.ready();
    }
    throw new IOException("Bluetooth not ready.");
  }

  public byte[] readBinary() throws IOException {
    return this.readBinary(4096);
  }

  public byte[] readBinary(int bufferSize) throws IOException {
    if (mReader != null) {
      byte[] buffer = new byte[bufferSize];
      int bytesRead = mInputStream.read(buffer);
      if (bytesRead == -1) {
        Log.e("Read failed.");
        throw new IOException("Read failed.");
      }
      byte[] truncatedBuffer = new byte[bytesRead];
      System.arraycopy(buffer, 0, truncatedBuffer, 0, bytesRead);
      return truncatedBuffer;
    }

    throw new IOException("Bluetooth not ready.");

  }

  public String read() throws IOException {
    return this.read(4096);
  }

  public String read(int bufferSize) throws IOException {
    if (mReader != null) {
      char[] buffer = new char[bufferSize];
      int bytesRead = mReader.read(buffer);
      if (bytesRead == -1) {
        Log.e("Read failed.");
        throw new IOException("Read failed.");
      }
      return new String(buffer, 0, bytesRead);
    }
    throw new IOException("Bluetooth not ready.");
  }

  public String readLine() throws IOException {
    if (mReader != null) {
      return mReader.readLine();
    }
    throw new IOException("Bluetooth not ready.");
  }

  public String getConnectedDeviceName() {
    return mDevice.getName();
  }

  private synchronized void clearFileDescriptor() {
    try {
      Field field = BluetoothSocket.class.getDeclaredField("mPfd");
      field.setAccessible(true);
      ParcelFileDescriptor mPfd = (ParcelFileDescriptor) field.get(mSocket);
      if (mPfd == null)
        return;
      mPfd.close();
      mPfd = null;
      try { field.set(mSocket, mPfd); }
      catch(Exception e) {
          Log.d("Exception setting mPfd = null in cleanCloseFix(): " + e.toString());
      }
    } catch (Exception e) {
        Log.w("ParcelFileDescriptor could not be cleanly closed.", e);
    }
  }

  public void stop() {
    if (mSocket != null) {
      try {
        clearFileDescriptor();
        mSocket.close();
      } catch (IOException e) {
        Log.e(e);
      }
    }
    mSocket = null;
    if (mServerSocket != null) {
      try {
        mServerSocket.close();
      } catch (IOException e) {
        Log.e(e);
      }
    }
    mServerSocket = null;

    if (mInputStream != null) {
      try {
        mInputStream.close();
      } catch (IOException e) {
        Log.e(e);
      }
    }
    mInputStream = null;
    if (mOutputStream != null) {
      try {
        mOutputStream.close();
      } catch (IOException e) {
        Log.e(e);
      }
    }
    mOutputStream = null;
    if (mReader != null) {
      try {
        mReader.close();
      } catch (IOException e) {
        Log.e(e);
      }
    }
    mReader = null;
  }
}
