#![allow(dead_code)]

use codec::{Decode, Encode, Input, Output};
use hex::FromHexError;

pub type BlockHash = primitive_types::H256;
pub type BlockNumber = u32;

#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockAnnouncesHandshake {
    pub roles: u8,
    pub best_number: BlockNumber,
    pub best_hash: BlockHash,
    pub genesis_hash: BlockHash,
}

impl BlockAnnouncesHandshake {
    pub fn from_genesis(genesis_hash: BlockHash) -> Self {
        Self {
            roles: 4,
            best_number: 0,
            best_hash: genesis_hash,
            genesis_hash,
        }
    }

    pub fn from_hex_genesis(genesis_hash: &str) -> Result<Self, FromHexError> {
        let raw_bytes = hex::decode(genesis_hash.trim_start_matches("0x"))?;
        let genesis_hash = primitive_types::H256::from_slice(raw_bytes.as_slice());
        Ok(Self::from_genesis(genesis_hash))
    }
}

mod role_bytes {
    pub const FULL_NODE: u8 = 0b_0000_0001;
    pub const LIGHT_NODE: u8 = 0b_0000_0010;
    pub const AUTHORITY: u8 = 0b_0000_0100;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProtocolRole {
    FullNode,
    LightNode,
    Authority,
}

impl ProtocolRole {
    pub fn encoded(&self) -> u8 {
        match self {
            ProtocolRole::FullNode => role_bytes::FULL_NODE,
            ProtocolRole::LightNode => role_bytes::LIGHT_NODE,
            ProtocolRole::Authority => role_bytes::AUTHORITY,
        }
    }
}

impl Encode for ProtocolRole {
    fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
        dest.push_byte(self.encoded())
    }
}

impl codec::Decode for ProtocolRole {
    fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
        let byte = input.read_byte()?;

        let role = match byte {
            role_bytes::FULL_NODE => ProtocolRole::FullNode,
            role_bytes::LIGHT_NODE => ProtocolRole::LightNode,
            role_bytes::AUTHORITY => ProtocolRole::Authority,
            _ => return Err(codec::Error::from("Invalid bytes")),
        };

        Ok(role)
    }
}
