use std::{cmp::Ordering, str::FromStr};
use url::Url;

#[derive(Debug, Clone, Copy, Eq)]
pub struct IconSize {
    pub width: u32,
    pub height: u32,
}

impl PartialEq for IconSize {
    fn eq(&self, other: &Self) -> bool {
        self.width == other.width && self.height == other.height
    }
}

impl PartialOrd for IconSize {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for IconSize {
    fn cmp(&self, other: &Self) -> Ordering {
        self.total_pixels().cmp(&other.total_pixels())
    }
}

impl IconSize {
    pub fn new(width: u32, height: u32) -> Self {
        Self { width, height }
    }

    pub fn total_pixels(&self) -> u32 {
        self.width * self.height
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IconInfo {
    pub url: Url,
    pub size: Option<IconSize>,
}

impl PartialOrd for IconInfo {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for IconInfo {
    fn cmp(&self, other: &Self) -> Ordering {
        let self_size = self.size.map(|s| s.total_pixels()).unwrap_or(0);
        let other_size = other.size.map(|s| s.total_pixels()).unwrap_or(0);

        self_size.cmp(&other_size)
    }
}

impl IconInfo {
    pub fn new(url: Url, sizes_prop: Option<&str>) -> Self {
        let size = sizes_prop.map(|sizes_str| {
            let width_height: Vec<&str> = sizes_str.split('x').collect();
            let width = width_height.first().and_then(|w| u32::from_str(w).ok()).unwrap_or(0);
            let height = width_height.get(1).and_then(|h| u32::from_str(h).ok()).unwrap_or(0);
            IconSize::new(width, height)
        });

        Self { url, size }
    }
}
