use std::io;
use byteorder::{ReadBytesExt, WriteBytesExt};
use protocol::raknet::packet::Packet;
use protocol::raknet::types;
use protocol::raknet::{NetworkSerializable, NetworkDeserializable, NetworkSize};

macro_rules! define_mcpe_packets {
    ($(($id:expr, $name:ident) => {$($field_name:ident: $field_type:ty),*}),+) => (
        #[derive(Debug)]
        pub enum PacketTypes {
            $($name($name)),+
        }

        impl PacketTypes {

            pub fn packet_id(&self) -> u8 {
                match self {
                    $(&PacketTypes::$name(ref packet) => packet.packet_id()),+
                }
            }
        }

        impl NetworkSerializable for PacketTypes {

            fn write_serialize(&self, stream: &mut io::Write) -> io::Result<()> {
                Ok(match self {
                    $(&PacketTypes::$name(ref packet) => {
                        stream.write_u8(packet.packet_id())?;
                        packet.write_serialize(stream)?;
                    },)+
                })
            }
        }

        impl NetworkDeserializable for PacketTypes {

            fn read_deserialize(stream: &mut io::Read) -> io::Result<Self> {
                Ok(match stream.read_u8()? {
                    $($id => PacketTypes::$name($name::read_deserialize(stream)?),)+
                    _ => return Err(io::Error::new(io::ErrorKind::InvalidData,
                                    "Unidentified MCPE packet"))
                })
            }
        }

        $(
            define_network_struct!($name => {$($field_name: $field_type),*});

            impl Packet for $name {
            }

            impl Into<PacketTypes> for $name {

                fn into(self) -> PacketTypes {
                    PacketTypes::$name(self)
                }
            }
        )+
    )
}

define_mcpe_packets!(
    (0x01, Login) => {
        protocol: u32,
        edition: u8

    }
);

                fn packet_id(&self) -> u8 {
                    $id as u8
                }