// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

use log::debug;
use serde::{Deserialize, Serialize};
use std::io;
use std::mem::transmute;
use std::prelude::v1::*;
use std::vec::Vec;
use teaclave_types::TeaclaveServiceResponseError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ProtocolError {
    #[error("IoError")]
    IoError(#[from] io::Error),
    #[error("SerdeError")]
    SerdeError(#[from] serde_json::error::Error),
    #[error(transparent)]
    Other(#[from] anyhow::Error),
}

impl From<ProtocolError> for TeaclaveServiceResponseError {
    fn from(error: ProtocolError) -> Self {
        match error {
            ProtocolError::IoError(e) => {
                TeaclaveServiceResponseError::ConnectionError(format!("{}", e))
            }
            ProtocolError::SerdeError(_) => {
                TeaclaveServiceResponseError::InternalError("serde".to_string())
            }
            ProtocolError::Other(_) => {
                TeaclaveServiceResponseError::InternalError("internal".to_string())
            }
        }
    }
}

pub(crate) struct JsonProtocol<'a, T>
where
    T: io::Read + io::Write,
{
    pub transport: &'a mut T,
    max_frame_len: u64,
}

impl<'a, T> JsonProtocol<'a, T>
where
    T: io::Read + io::Write,
{
    pub fn new(transport: &'a mut T) -> JsonProtocol<'a, T> {
        Self {
            transport,
            // Default max frame length is 8MB
            max_frame_len: 8 * 1_024 * 1_024,
        }
    }

    pub fn read_message<V>(&mut self) -> std::result::Result<V, ProtocolError>
    where
        V: for<'de> Deserialize<'de> + std::fmt::Debug,
    {
        let mut header = [0u8; 8];

        self.transport.read_exact(&mut header)?;
        let buf_len = u64::from_be(unsafe { transmute::<[u8; 8], u64>(header) });

        if buf_len > self.max_frame_len {
            return Err(ProtocolError::Other(anyhow::anyhow!(
                "Exceed max frame length"
            )));
        }

        let mut recv_buf: Vec<u8> = vec![0u8; buf_len as usize];
        self.transport.read_exact(&mut recv_buf)?;

        debug!("Recv: {}", std::string::String::from_utf8_lossy(&recv_buf));
        let r: V = serde_json::from_slice(&recv_buf)?;

        Ok(r)
    }

    pub fn write_message<U>(&mut self, message: U) -> std::result::Result<(), ProtocolError>
    where
        U: Serialize + std::fmt::Debug,
    {
        let send_buf = serde_json::to_vec(&message)?;

        debug!("Send: {}", std::string::String::from_utf8_lossy(&send_buf));

        let buf_len = send_buf.len() as u64;
        let header = unsafe { transmute::<u64, [u8; 8]>(buf_len.to_be()) };

        self.transport.write(&header)?;
        self.transport.write_all(&send_buf)?;
        self.transport.flush()?;

        Ok(())
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "result")]
#[serde(rename_all = "snake_case")]
pub enum JsonProtocolResult<T, E> {
    Ok(T),
    Err(E),
}

impl<T, E> From<std::result::Result<T, E>> for JsonProtocolResult<T, E> {
    fn from(result: std::result::Result<T, E>) -> Self {
        match result {
            Ok(t) => JsonProtocolResult::Ok(t),
            Err(e) => JsonProtocolResult::Err(e),
        }
    }
}

impl<T, E> From<JsonProtocolResult<T, E>> for std::result::Result<T, E> {
    fn from(result: JsonProtocolResult<T, E>) -> Self {
        match result {
            JsonProtocolResult::Ok(t) => Ok(t),
            JsonProtocolResult::Err(e) => Err(e),
        }
    }
}
