// Copyright 2022 Google LLC
//
// 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
//
//     https://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.

use core::cell::Cell;
use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared};
use matcha_hal::dprintf;
use matcha_hal::mailbox_hal::MailboxHAL;

use matcha_config::*;

//------------------------------------------------------------------------------

pub struct AppData {
    pub send_callback: Option<Callback>,
    pub recv_callback: Option<Callback>,
    pub send_buffer: Option<AppSlice<Shared, u8>>,
    pub recv_buffer: Option<AppSlice<Shared, u8>>,
}

impl Default for AppData {
    fn default() -> AppData {
        AppData {
            send_callback: None,
            recv_callback: None,
            send_buffer: None,
            recv_buffer: None,
        }
    }
}

//------------------------------------------------------------------------------
// MailboxCapsule is a global static singleton - its members have to be
// pseudo-const.

pub struct MailboxCapsule {
    pub app_data_grant: Grant<AppData>,
    pub mailbox_hal: Cell<Option<&'static dyn MailboxHAL>>,
    pub current_app: Cell<Option<AppId>>,
}

//----------------------------------------

impl MailboxCapsule {
    pub fn new(app_data_grant: Grant<AppData>) -> Self {
        return MailboxCapsule {
            app_data_grant: app_data_grant,
            mailbox_hal: Cell::new(None),
            current_app: Cell::new(None),
        };
    }

    pub fn set_mailbox(&self, mailbox: &'static dyn MailboxHAL) {
        self.mailbox_hal.set(Some(mailbox));
    }

    pub fn handle_command(
        &self,
        app_id: AppId,
        app_data: &mut AppData,
        cmd_num: usize,
        arg2: usize,
        _arg3: usize,
    ) -> ReturnCode {
        match cmd_num {
            CMD_MAILBOX_INIT => {
                self.current_app.set(Some(app_id));
                ReturnCode::SUCCESS
            }
            CMD_MAILBOX_SEND => {
                let message_len = arg2;
                match &app_data.send_buffer {
                    Some(buffer) => {
                        self.mailbox_hal.get().map(|mb| {
                            let _ = mb.send_message_slice_sync(message_len, buffer);
                        });
                        ReturnCode::SUCCESS
                    }
                    None => ReturnCode::FAIL,
                }
            }
            CMD_MAILBOX_RECV => {
                // Nothing to do here yet?
                ReturnCode::SUCCESS
            }
            _ => {
                dprintf!("MailboxCapsule::handle_command({:?}, ????)\n", app_id);
                ReturnCode::EINVAL
            }
        }
    }

    pub fn handle_subscribe(
        &self,
        _app_id: AppId,
        app_data: &mut AppData,
        minor_num: usize,
        callback: Option<Callback>,
    ) -> ReturnCode {
        match minor_num {
            CMD_MAILBOX_SEND => {
                app_data.send_callback = callback;
                ReturnCode::SUCCESS
            }
            CMD_MAILBOX_RECV => {
                app_data.recv_callback = callback;
                ReturnCode::SUCCESS
            }
            _ => ReturnCode::EINVAL,
        }
    }

    pub fn handle_allow(
        &self,
        _app_id: AppId,
        app_data: &mut AppData,
        minor_num: usize,
        slice: Option<AppSlice<Shared, u8>>,
    ) -> ReturnCode {
        match minor_num {
            CMD_MAILBOX_SEND => {
                app_data.send_buffer = slice;
                ReturnCode::SUCCESS
            }
            CMD_MAILBOX_RECV => {
                app_data.recv_buffer = slice;
                ReturnCode::SUCCESS
            }
            _ => ReturnCode::EINVAL,
        }
    }
}

//------------------------------------------------------------------------------
// Our "driver" trait impl just unwraps the app data grant and delegates to
// MailboxCapsule.

impl Driver for MailboxCapsule {
    fn subscribe(&self, minor_num: usize, callback: Option<Callback>, app_id: AppId) -> ReturnCode {
        self.app_data_grant
            .enter(app_id, |app_data, _| {
                self.handle_subscribe(app_id, app_data, minor_num, callback)
            })
            .unwrap_or_else(|err| err.into())
    }

    fn command(&self, cmd_num: usize, r2: usize, r3: usize, app_id: AppId) -> ReturnCode {
        self.app_data_grant
            .enter(app_id, |app_data, _| {
                self.handle_command(app_id, app_data, cmd_num, r2, r3)
            })
            .unwrap_or_else(|err| err.into())
    }

    fn allow(
        &self,
        app_id: AppId,
        minor_num: usize,
        slice: Option<AppSlice<Shared, u8>>,
    ) -> ReturnCode {
        self.app_data_grant
            .enter(app_id, |app_data, _| {
                self.handle_allow(app_id, app_data, minor_num, slice)
            })
            .unwrap_or_else(|err| err.into())
    }
}

//------------------------------------------------------------------------------

impl matcha_hal::mailbox_hal::MailboxISR for MailboxCapsule {
    fn on_wtirq(&self) {
        // Nothing to do here at the moment, sends are synchronous and the
        // polarity of the ISR is backwards.
    }

    // When a message arrives, we copy it to the waiting app's buffer (if there
    // is one) and then fire the app's callback. Async waiting is handled in
    // app/src/mailbox_client.rs
    fn on_rtirq(&self) {
        // Unwrap all our optionals. There's probably a better way to do this.
        self.current_app.get().map(|app_id| {
            self.app_data_grant.enter(app_id, |app_data, _| {
                app_data.recv_buffer.as_ref().map(|buffer| {
                    self.mailbox_hal.get().map(|mailbox| {
                        // Copy the message to the app's buffer and then
                        // schedule the app callback.
                        match mailbox.get_message_slice_sync(&buffer) {
                            Ok(len) => {
                                let page = mailbox.get_message_page().unwrap_or(0);
                                app_data.recv_callback.map(|mut callback| {
                                    callback.schedule(1, len, page as usize);
                                });
                            }
                            Err(len) => {
                                app_data.recv_callback.map(|mut callback| {
                                    callback.schedule(0, len, 0);
                                });
                            }
                        }
                    });
                });
            })
        });
    }

    fn on_eirq(&self) {
        // We should probably do something here eventually.
    }
}
