use std::convert::TryFrom;
use std::str;
use std::io::Read;
use super::error::{Error, Result};
use serde::de::{
    self,
    Deserialize,
    DeserializeOwned,
    Visitor,
    DeserializeSeed,
    IntoDeserializer
};

#[allow(dead_code)]
pub fn from_vec<T: DeserializeOwned>(vec: &Vec<u8>) -> Result<T> {
    let mut slice = vec.as_slice();
    let result = from_read(&mut slice);
    result
}

#[allow(dead_code)]
pub fn from_read<T: DeserializeOwned, R: Read>(read: &mut R) -> Result<T> {
    let mut de = Deserializer::new(read);
    let result = Deserialize::deserialize(&mut de);
    result
}

pub struct Deserializer<'de, T: Read + ?Sized> {
    input: &'de mut T,
}

fn try_from<TSource, TDest: TryFrom<TSource>>(value: TSource) -> Result<TDest> {
    let cast = TDest::try_from(value).or_else(|_| Err(Error::TypeConversion))?;
    Ok(cast)
}

/// Returns the number of bytes needed to store the unicode character in UTF-9 whose
/// encoding begins with the given byte. If the given byte is not valid as the first byte
/// for any character, then a failed result with Error::InvalidUtf7Char is returned.
fn num_bytes_for_char(first_byte: u8) -> Result<usize> {
    if first_byte & 128u8 == 0  {
        return Ok(1);
    }
    for bit in 2..5 {
        let mask = 128u8 >> bit;
        if mask & first_byte == 0 {
            return Ok(bit);
        }
    }
    Err(Error::InvalidUtf8Char)
}

/// Returns the unicode code point of the character that is encoded in UTF-8 in the given buffer
/// as a u32. If the given buffer is not of a valid length then a failed result is returned.
/// No other verification is performed.
fn u32_from_utf8(buf: &[u8]) -> Result<u32> {
    const MASK: u8 = 0b0011_1111;

    fn mask(byte: u8, mask: u8) -> u32 {
        (byte & mask) as u32
    }

    fn two_bytes(buf: &[u8]) -> u32 {
       mask(buf[0], 0b0001_1111) << 6 | mask(buf[1], MASK)
    }

    fn three_bytes(buf: &[u8]) -> u32 {
        mask(buf[0], 0b0000_1111) << 12 | mask(buf[1], MASK) << 6 | mask(buf[2], MASK)
    }

    fn four_bytes(buf: &[u8]) -> u32 {
        mask(buf[0], 0b0000_0111) << 18 | mask(buf[1], MASK) << 12 | mask(buf[2], MASK) << 6
            | mask(buf[3], MASK)
    }

    let code_point = match buf.len() {
        1 => Some(buf[0] as u32),
        2 => Some(two_bytes(buf)),
        3 => Some(three_bytes(buf)),
        4 => Some(four_bytes(buf)),
        _ => None
    };
    code_point.ok_or(Error::InvalidUtf8Char)
}

fn char_from_utf8(buf: &[u8]) -> Result<char> {
    let result = u32_from_utf8(buf);
    let option = char::from_u32(result?);
    option.ok_or(Error::InvalidUtf8Char)
}

impl<'de, T: Read + ?Sized> Deserializer<'de, T> {
    pub fn new(input: &'de mut T) -> Self {
        Deserializer { input: input }
    }

    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
        self.input.read_exact(buf).or_else(|e| Err(Error::Io(e)))?;
        Ok(())
    }

    fn read_u8(&mut self) -> Result<u8> {
        let mut buf = [0u8; 1];
        self.read_exact(&mut buf)?;
        Ok(buf[0])
    }

    fn read_u16(&mut self) -> Result<u16> {
        let mut buf = [0u8; 2];
        self.read_exact(&mut buf)?;
        Ok(u16::from_le_bytes(buf))
    }

    fn read_u32(&mut self) -> Result<u32> {
        let mut buf = [0u8; 4];
        self.read_exact(&mut buf)?;
        Ok(u32::from_le_bytes(buf))
    }

    fn read_u64(&mut self) -> Result<u64> {
        let mut buf = [0u8; 8];
        self.read_exact(&mut buf)?;
        Ok(u64::from_le_bytes(buf))
    }

    fn read_i8(&mut self) -> Result<i8> {
        let value = self.read_u8()?;
        Ok(value as i8)
    }

    fn read_i16(&mut self) -> Result<i16> {
        let value = self.read_u16()?;
        Ok(value as i16)
    }

    fn read_i32(&mut self) -> Result<i32> {
        let value = self.read_u32()?;
        Ok(value as i32)
    }

    fn read_bool(&mut self) -> Result<bool> {
        let byte = self.read_u8()?;
        Ok(byte > 0)
    }

    fn read_vec(&mut self) -> Result<Vec<u8>> {
        let len = try_from(self.read_u32()?)?;
        let mut vec = vec![0; len];
        self.read_exact(vec.as_mut_slice())?;
        Ok(vec)
    }

    fn read_string(&mut self) -> Result<String> {
        let vec = self.read_vec()?;
        let value = String::from_utf8(vec).or_else(|_| Err(Error::TypeConversion))?;
        Ok(value)
    }
}

impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
        Err(Error::Message("deserialize_any is not supported".to_string()))
    }

    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_bool()?;
        visitor.visit_bool(value)
    }

    fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_i8()?;
        visitor.visit_i8(value)
    }

    fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_i16()?;
        visitor.visit_i16(value)
    }

    fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_i32()?;
        visitor.visit_i32(value)
    }

    fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let unsigned = self.read_u64()?;
        let signed = unsigned as i64;
        visitor.visit_i64(signed)
    }

    fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_u8()?;
        visitor.visit_u8(value)
    }

    fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_u16()?;
        visitor.visit_u16(value)
    }

    fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_u32()?;
        visitor.visit_u32(value)
    }

    fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_u64()?;
        visitor.visit_u64(value)
    }

    fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let mut buf = [0u8; 4];
        self.read_exact(&mut buf)?;
        let value = f32::from_le_bytes(buf);
        visitor.visit_f32(value)
    }

    fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let mut buf = [0u8; 8];
        self.read_exact(&mut buf)?;
        let value = f64::from_le_bytes(buf);
        visitor.visit_f64(value)
    }

    fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let byte = self.read_u8()?;
        let buf_len = num_bytes_for_char(byte);
        let mut buf = vec![0; buf_len?];
        buf[0] = byte;
        self.read_exact(&mut buf[1..])?;
        let result = char_from_utf8(&buf);
        visitor.visit_char(result?)
    }

    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_string()?;
        visitor.visit_str(value.as_str())
    }

    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_string()?;
        visitor.visit_string(value)
    }

    fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_vec()?;
        visitor.visit_bytes(value.as_slice())
    }

    fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let value = self.read_vec()?;
        visitor.visit_byte_buf(value)
    }

    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let some = self.read_bool()?;
        if some {
            visitor.visit_some(self)
        } 
        else {
            visitor.visit_none()
        }
    }

    fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_unit()
    }

    fn deserialize_unit_struct<V: Visitor<'de>>(
        self, _name: &'static str, visitor: V
    ) -> Result<V::Value> {
        visitor.visit_unit()
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self, _name: &'static str, visitor: V
    ) -> Result<V::Value> {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let len = self.read_u32()?;
        visitor.visit_seq(SeqAccess { elements_left: len, deserializer: self})
    }

    fn deserialize_tuple<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
        visitor.visit_seq(SeqAccess { elements_left: try_from(len)?, deserializer: self})
    }

    fn deserialize_tuple_struct<V: Visitor<'de>>(
        self, _name: &'static str, len: usize, visitor: V
    ) -> Result<V::Value> {
        self.deserialize_tuple(len, visitor)
    }

    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        let len = self.read_u32()?;
        visitor.visit_map(SeqAccess { elements_left: len, deserializer: self})
    }

    fn deserialize_struct<V: Visitor<'de>>(
        self, _name: &'static str, fields: &'static [&'static str], visitor: V
    ) -> Result<V::Value> {
        self.deserialize_tuple(fields.len(), visitor)
    }

    fn deserialize_enum<V: Visitor<'de>>(
        self, _name: &'static str, _variants: &'static [&'static str], visitor: V
    ) -> Result<V::Value> {
        visitor.visit_enum(self)
    }

    fn deserialize_identifier<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
        Err(Error::NotSupported("Deserializer::deserialize_identifier"))
    }

    fn deserialize_ignored_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
        Err(Error::NotSupported("Deserializer::deserialize_ignored_any"))
    }

    fn is_human_readable(&self) -> bool {
        false
    }
}

struct SeqAccess<'a, 'de, T: Read> {
    elements_left: u32,
    deserializer: &'a mut Deserializer<'de, T>
}

impl<'a, 'de, T: Read> de::SeqAccess<'de> for SeqAccess<'a, 'de, T> {
    type Error = Error;

    fn next_element_seed<S: DeserializeSeed<'de>>(&mut self, seed: S) -> Result<Option<S::Value>> {
        if 0 == self.elements_left {
            return Ok(None)
        }

        self.elements_left -= 1;
        seed.deserialize(&mut *self.deserializer).map(Some)
    }
}

impl<'a, 'de, T: Read> de::MapAccess<'de> for SeqAccess<'a, 'de, T> {
    type Error = Error;

    fn next_key_seed<S: DeserializeSeed<'de>>(&mut self, seed: S) -> Result<Option<S::Value>> {
        if 0 == self.elements_left {
            return Ok(None)
        }

        self.elements_left -= 1;
        seed.deserialize(&mut *self.deserializer).map(Some)
    }

    fn next_value_seed<U: DeserializeSeed<'de>>(&mut self, seed: U) -> Result<U::Value> {
        seed.deserialize(&mut *self.deserializer)
    }
}

impl<'de, T: Read> de::VariantAccess<'de> for &mut Deserializer<'de, T> {
    type Error = Error;

    fn unit_variant(self) -> Result<()> {
        Ok(())
    }

    fn newtype_variant_seed<S: DeserializeSeed<'de>>(self, seed: S) -> Result<S::Value> {
        seed.deserialize(self)
    }

    fn tuple_variant<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
        de::Deserializer::deserialize_tuple(self, len, visitor)
    }

    fn struct_variant<V: Visitor<'de>>(
        self, fields: &'static [&'static str], visitor: V
    ) -> Result<V::Value> {
        de::Deserializer::deserialize_struct(self, "", fields, visitor)
    }
}

impl<'a, 'de, T: Read> de::EnumAccess<'de> for &mut Deserializer<'de, T> {
    type Error = Error;
    type Variant = Self;
    
    fn variant_seed<S: DeserializeSeed<'de>>(self, seed: S) -> Result<(S::Value, Self::Variant)> {
        let int = self.read_u16()?;
        let index: u32 = try_from(int)?;
        let value = seed.deserialize(index.into_deserializer())?;
        Ok((value, self))
    }
}

mod test {
    #[allow(unused_imports)]
    use serde::Deserialize;
    #[allow(unused_imports)]
    use super::{
        from_vec,
        num_bytes_for_char,
        Result,
        Deserializer
    };
    #[allow(unused_imports)]
    use std::collections::HashMap;
    
    #[test]
    fn new() -> Result<()> {
        let vec: Vec<u8> = vec![0xA1, 0x42, 0x71, 0xAC];
        let mut slice = vec.as_slice();
        let de = Deserializer::new(&mut slice);
        assert_eq!(&vec.as_slice(), de.input);
        Ok(())
    }

    #[test]
    fn test_num_bytes_for_char() -> Result<()> {
        fn test_case(c: char) -> Result<()> {
            let len = c.len_utf8();
            let mut buf: Vec<u8> = vec![0; len];
            c.encode_utf8(buf.as_mut_slice());
            let result = num_bytes_for_char(buf[0]);
            assert_eq!(len, result?);
            Ok(())
        }

        test_case('$')?;
        test_case('£')?;
        test_case('€')?;
        test_case('😑')?;
        Ok(())
    }

    #[test]
    fn deserialize_false() -> Result<()> {
        let vec: Vec<u8> = vec![0x00];
        let result = from_vec(&vec);
        assert_eq!(false, result?);
        Ok(())
    }

    #[test]
    fn deserialize_true() -> Result<()> {
        let vec: Vec<u8> = vec![0x01];
        let result = from_vec(&vec);
        assert_eq!(true, result?);
        Ok(())
    }

    #[test]
    fn deserialize_i8() -> Result<()> {
        let vec: Vec<u8> = vec![0xFE];
        let result = from_vec(&vec);
        assert_eq!(-2i8, result?);
        Ok(())
    }

    #[test]
    fn deserialize_i16() -> Result<()> {
        let vec: Vec<u8> = vec![0xFD, 0xFF];
        let result = from_vec(&vec);
        assert_eq!(-3i16, result?);
        Ok(())
    }

    #[test]
    fn deserialize_i32() -> Result<()> {
        let vec: Vec<u8> = vec![0xFE, 0xFF, 0xFF, 0xFF];
        let result = from_vec(&vec);
        assert_eq!(-2i32, result?);
        Ok(())
    }

    #[test]
    fn deserialize_i64() -> Result<()> {
        let vec: Vec<u8> = vec![0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
        let result = from_vec(&vec);
        assert_eq!(-2i64, result?);
        Ok(())
    }

    #[test]
    fn deserialize_u8() -> Result<()> {
        let vec: Vec<u8> = vec![0xFF];
        let result = from_vec(&vec);
        assert_eq!(255u8, result?);
        Ok(())
    }

    #[test]
    fn deserialize_u16() -> Result<()> {
        let vec: Vec<u8> = vec![0xFE, 0xFF];
        let result = from_vec(&vec);
        assert_eq!(0xFFFEu16, result?);
        Ok(())
    }

    #[test]
    fn deserialize_u32() -> Result<()> {
        let vec: Vec<u8> = vec![0xFE, 0xFF, 0xFF, 0xFF];
        let result = from_vec(&vec);
        assert_eq!(0xFFFFFFFEu32, result?);
        Ok(())
    }

    #[test]
    fn deserialize_u64() -> Result<()> {
        let vec: Vec<u8> = vec![0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
        let result = from_vec(&vec);
        assert_eq!(0xFFFFFFFFFFFFFFFEu64, result?);
        Ok(())
    }

    #[test]
    fn deserialize_f32() -> Result<()> {
        let vec: Vec<u8> = vec![0x00, 0x00, 0x20, 0x3E];
        let result = from_vec(&vec);
        assert_eq!(0.15625f32, result?);
        Ok(())
    }

    #[test]
    fn deserialize_f64() -> Result<()> {
        let vec: Vec<u8> = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F];
        let result = from_vec(&vec);
        assert_eq!(1f64, result?);
        Ok(())
    }

    #[test]
    fn deserialize_char() -> Result<()> {
        fn test_case(c: char, vec: Vec<u8>) -> Result<()> {
            let result = from_vec(&vec);
            assert_eq!(c, result?);
            Ok(())
        }

        test_case('*', vec![0x2A])?;
        test_case('£', vec![0xC2, 0xA3])?;
        test_case('€', vec![0xE2, 0x82, 0xAC])?;
        test_case('😎', vec![0xF0, 0x9F, 0x98, 0x8E])?;
        Ok(())
    }

    #[test]
    fn deserialize_string() -> Result<()> {
        let vec: Vec<u8> = vec![
            0x06, 0x00, 0x00, 0x00,
            'l' as u8, 'o' as u8, 'c' as u8, 'a' as u8, 's' as u8, 'h' as u8
        ];
        let result: Result<String> = from_vec(&vec);
        assert_eq!("locash", result?);
        Ok(())
    }

    #[test]
    fn deserialize_byte_buf() -> Result<()> {
        let vec: Vec<u8> = vec![0x04, 0x00, 0x00, 0x00, 0x42, 0x91, 0xBE, 0xEF];
        let result: Result<Vec<u8>> = from_vec(&vec);
        assert_eq!(&vec[4..], result?);
        Ok(())
    }

    #[test]
    fn deserialize_none() -> Result<()> {
        let vec: Vec<u8> = vec![0x00];
        let result: Result<Option<u8>> = from_vec(&vec);
        assert_eq!(None, result?);
        Ok(())
    }

    #[test]
    fn deserialize_some() -> Result<()> {
        let vec: Vec<u8> = vec![0x01, 0xD5];
        let result: Result<Option<u8>> = from_vec(&vec);
        assert_eq!(Some(0xD5u8), result?);
        Ok(())
    }

    #[test]
    fn deserialize_tuple() -> Result<()> {
        let expected = ("orb".to_string(), 12u16);
        let vec: Vec<u8> = vec![
            0x03, 0x00, 0x00, 0x00, 'o' as u8, 'r' as u8, 'b' as u8,
            0x0C, 0x00
        ];
        let result = from_vec(&vec);
        assert_eq!(expected, result?);
        Ok(())
    }

    #[test]
    fn deserialize_map() -> Result<()> {
        let expected: HashMap<String, u8> = HashMap::from([
            ("blue".to_string(), 5), ("red".to_string(), 7)
        ]);
        let vec: Vec<u8> = vec![
            0x02, 0x00, 0x00, 0x00, // Number of entries in the map.
            0x04, 0x00, 0x00, 0x00, 'b' as u8, 'l' as u8, 'u' as u8, 'e' as u8, // First key.
            0x05, // First value.
            0x03, 0x00, 0x00, 0x00, 'r' as u8, 'e' as u8, 'd' as u8, // Second key.
            0x07, // Second value.
        ];
        let result = from_vec(&vec);
        assert_eq!(expected, result?);
        Ok(())
    }

    #[test]
    fn deserialize_struct() -> Result<()> {
        #[derive(Debug, PartialEq, Deserialize)]
        struct Order {
            customer: String,
            item_id: u16,
            quantity: u8
        }
        let expected = Order {
            customer: "Bob".to_string(),
            item_id: 256,
            quantity: 255
        };
        let vec: Vec<u8> = vec![
            0x03, 0x00, 0x00, 0x00, 'B' as u8, 'o' as u8, 'b' as u8,
            0x00, 0x01,
            0xFF 
        ];
        let result = from_vec(&vec);
        assert_eq!(expected, result?);
        Ok(())
    }

    #[test]
    fn deserialize_enum() -> Result<()> {
        #[derive(Debug, PartialEq, Deserialize)]
        enum Emotions { Anguish, Catharsis }
        let vec: Vec<u8> = vec![0x01, 0x00];
        let result = from_vec(&vec);
        assert_eq!(Emotions::Catharsis, result?);
        Ok(())
    }

    #[test]
    fn deserialize_struct_variant() -> Result<()> {
        #[derive(Debug, PartialEq, Deserialize)]
        enum Vector {
            Dim2(i32, i32),
            Dim3(i32, i32, i32)
        }
        let expected = Vector::Dim3(1, -1, -2);
        let vec: Vec<u8> = vec![
            0x01, 0x00, // The variant index.
            0x01, 0x00, 0x00, 0x00, // The first entry.
            0xFF, 0xFF, 0xFF, 0xFF, // The second entry.
            0xFE, 0xFF, 0xFF, 0xFF // The last entry.
        ];
        let result = from_vec(&vec);
        assert_eq!(expected, result?);
        Ok(())
    }
}