use crate::ip_type::IpType;
use crate::cidr_ip::CidrIp;
use crate::error::Error;
pub struct IpAddress{
    pub address: String,
}

impl IpAddress{
    pub fn new(input:String) -> Result<Self,Error>{
        Ok(IpAddress{
            address:input,
        })
    }

    pub fn get_ip_parts(ip:&str)->Vec<u8>{
        ip.split(".").map(|x| x.parse().expect("Error in parsing the ip")).collect()
    }

    pub fn parts_to_decimal(ip_parts:Vec<u8>) -> u32 {
        (ip_parts[0] as u32) << 24 | (ip_parts[1] as u32) << 16 | (ip_parts[2] as u32) << 8 | (ip_parts[3] as u32)
    }

    pub fn get_ip_type(&self) ->Result<IpType,Error>{
        let localhost_range=CidrIp::new("127.0.0.0/8".to_string())?;
        let private_range_1=CidrIp::new("10.0.0.0/8".to_string())?;
        let private_range_2=CidrIp::new("172.16.0.0/12".to_string())?;
        let private_range_3=CidrIp::new("192.0.0.0/24".to_string())?;
        let current_range=CidrIp::new("0.0.0.0/8".to_string())?;

        if localhost_range.is_within_range(self){
            Ok(IpType::LocalHost)
        }
        else if private_range_1.is_within_range(self) || private_range_2.is_within_range(self) || private_range_3.is_within_range(self) {
            Ok(IpType::Private)            
        }
        else if current_range.is_within_range(self) {
            Ok(IpType::Current)
        }
        else{
            Ok(IpType::Public)
        }
    }
}
