// Copyright 2021, The Android Open Source Project
//
// 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.

//! Implementation of the HAl that talks to NFC controller over Android's HIDL
use crate::internal::InnerHal;
#[allow(unused)]
use crate::{is_control_packet, Hal, HalEvent, HalEventRegistry, HalEventStatus, Result};
use log::{debug, error};
use nfc_packets::nci::{DataPacket, NciPacket};
use pdl_runtime::Packet;
use std::sync::Mutex;
use tokio::select;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use tokio::sync::oneshot;

/// Initialize the module
pub async fn init() -> Hal {
    let (raw_hal, inner_hal) = InnerHal::new();
    let (hal_open_evt_tx, hal_open_evt_rx) = oneshot::channel::<ffi::NfcStatus>();
    let (hal_close_evt_tx, hal_close_evt_rx) = oneshot::channel::<ffi::NfcStatus>();
    *CALLBACKS.lock().unwrap() = Some(Callbacks {
        hal_open_evt_tx: Some(hal_open_evt_tx),
        hal_close_evt_tx: Some(hal_close_evt_tx),
        in_cmd_tx: inner_hal.in_cmd_tx,
        in_data_tx: inner_hal.in_data_tx,
    });
    ffi::start_hal();
    hal_open_evt_rx.await.unwrap();

    tokio::spawn(dispatch_outgoing(
        raw_hal.hal_events.clone(),
        inner_hal.out_cmd_rx,
        inner_hal.out_data_rx,
        hal_close_evt_rx,
    ));

    raw_hal
}

#[cxx::bridge(namespace = nfc::hal)]
// TODO Either use or remove these functions, this shouldn't be the long term state
#[allow(dead_code)]
#[allow(unsafe_op_in_unsafe_fn)]
mod ffi {

    #[repr(u32)]
    #[derive(Debug)]
    enum NfcEvent {
        OPEN_CPLT = 0,
        CLOSE_CPLT = 1,
        POST_INIT_CPLT = 2,
        PRE_DISCOVER_CPLT = 3,
        REQUEST_CONTROL = 4,
        RELEASE_CONTROL = 5,
        ERROR = 6,
        HCI_NETWORK_RESET = 7,
    }

    #[repr(u32)]
    #[derive(Debug)]
    enum NfcStatus {
        OK = 0,
        FAILED = 1,
        ERR_TRANSPORT = 2,
        ERR_CMD_TIMEOUT = 3,
        REFUSED = 4,
    }

    unsafe extern "C++" {
        include!("hal/ffi/hidl.h");
        fn start_hal();
        fn stop_hal();
        fn send_command(data: &[u8]);

        #[namespace = "android::hardware::nfc::V1_1"]
        type NfcEvent;

        #[namespace = "android::hardware::nfc::V1_0"]
        type NfcStatus;
    }

    extern "Rust" {
        fn on_event(evt: NfcEvent, status: NfcStatus);
        fn on_data(data: &[u8]);
    }
}

impl From<ffi::NfcStatus> for HalEventStatus {
    fn from(ffi_nfc_status: ffi::NfcStatus) -> Self {
        match ffi_nfc_status {
            ffi::NfcStatus::OK => HalEventStatus::Success,
            ffi::NfcStatus::FAILED => HalEventStatus::Failed,
            ffi::NfcStatus::ERR_TRANSPORT => HalEventStatus::TransportError,
            ffi::NfcStatus::ERR_CMD_TIMEOUT => HalEventStatus::Timeout,
            ffi::NfcStatus::REFUSED => HalEventStatus::Refused,
            _ => HalEventStatus::Failed,
        }
    }
}

struct Callbacks {
    hal_open_evt_tx: Option<oneshot::Sender<ffi::NfcStatus>>,
    hal_close_evt_tx: Option<oneshot::Sender<ffi::NfcStatus>>,
    in_cmd_tx: UnboundedSender<NciPacket>,
    in_data_tx: UnboundedSender<DataPacket>,
}

static CALLBACKS: Mutex<Option<Callbacks>> = Mutex::new(None);

fn on_event(evt: ffi::NfcEvent, status: ffi::NfcStatus) {
    debug!("got event: {:?} with status {:?}", evt, status);
    let mut callbacks = CALLBACKS.lock().unwrap();
    match evt {
        ffi::NfcEvent::OPEN_CPLT => {
            if let Some(evt_tx) = callbacks.as_mut().unwrap().hal_open_evt_tx.take() {
                evt_tx.send(status).unwrap();
            }
        }
        ffi::NfcEvent::CLOSE_CPLT => {
            if let Some(evt_tx) = callbacks.as_mut().unwrap().hal_close_evt_tx.take() {
                evt_tx.send(status).unwrap();
            }
        }
        _ => error!("Unhandled HAL event {:?}", evt),
    }
}

fn on_data(data: &[u8]) {
    debug!("got packet: {:02x?}", data);
    let callbacks = CALLBACKS.lock().unwrap();
    if is_control_packet(data) {
        match NciPacket::parse(data) {
            Ok(p) => callbacks.as_ref().unwrap().in_cmd_tx.send(p).unwrap(),
            Err(e) => error!("failure to parse response: {:?} data: {:02x?}", e, data),
        }
    } else {
        match DataPacket::parse(data) {
            Ok(p) => callbacks.as_ref().unwrap().in_data_tx.send(p).unwrap(),
            Err(e) => error!("failure to parse response: {:?} data: {:02x?}", e, data),
        }
    }
}

async fn dispatch_outgoing(
    mut hal_events: HalEventRegistry,
    mut out_cmd_rx: UnboundedReceiver<NciPacket>,
    mut out_data_rx: UnboundedReceiver<DataPacket>,
    hal_close_evt_rx: oneshot::Receiver<ffi::NfcStatus>,
) {
    loop {
        select! {
            Some(cmd) = out_cmd_rx.recv() => ffi::send_command(&cmd.encode_to_bytes().unwrap()),
            Some(data) = out_data_rx.recv() => ffi::send_command(&data.encode_to_bytes().unwrap()),
            else => break,
        }
    }
    ffi::stop_hal();
    let status = hal_close_evt_rx.await.unwrap();
    if let Some(evt) = hal_events.unregister(HalEvent::CloseComplete).await {
        evt.send(HalEventStatus::from(status)).unwrap();
    }
}
