use super::{
    methods::Method,
    request::{MediaType, Request},
    response::{Outcome, Response, Status},
};

pub struct RoutInfo {
    name: Option<&'static str>,
    method: Method,
    path: &'static str,
    handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
    format: Option<MediaType>,
    rank: Option<isize>,
}

#[derive(Clone, Copy)]
pub struct Route<'a> {
    pub name: Option<&'static str>,
    pub method: Method,
    pub uri: Uri<'a>,
    pub handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
    pub rank: isize,
    pub format: Option<MediaType>,
}

impl Route<'_> {
    pub fn from(routeinfo: RoutInfo) -> Self {
        let rank = routeinfo.rank.unwrap_or(0);
        Route {
            name: routeinfo.name,
            method: routeinfo.method,
            uri: routeinfo.path,
            handler: routeinfo.handler,
            rank,
            format: routeinfo.format,
        }
    }
    pub fn compare_uri(self, uri: Uri) -> bool {
        let mut iter_comp_str = uri.split("/");
        for true_str in self.uri.split("/") {
            let comp_str = if let Some(str) = iter_comp_str.next() {
                str
            } else {
                return false;
            };
            if true_str.starts_with("<") && true_str.ends_with("..>") {
                return true;
            }
            if true_str.starts_with("<") && true_str.ends_with(">") {
                continue;
            }
            if true_str != comp_str {
                return false;
            }
        }
        true
    }
}

pub type Uri<'a> = &'a str;

#[derive(Debug, Clone)]
pub struct Body {
    pub body: Vec<u8>,
}

#[derive(Debug, Clone)]
pub struct Data {
    pub buffer: Vec<u8>,
    pub is_complete: bool,
}

impl Data {
    pub fn is_empty(&self) -> bool {
        self.buffer.len() == 0
    }
}