Documentation
// Copyright 2022 Parthka. All rights reserved. MIT license.

use super::types::{HandFn, Route};
use super::Method;

// router path and handler
#[derive(Clone)]
pub struct Router {
    pub routes: Vec<Route>,
}

impl Router {
    // new router
    pub fn new() -> Self {
        Router { routes: Vec::new() }
    }

    // add route
    pub fn add(&mut self, path: &'static str, method: Method, hand: HandFn) {
        // create new route
        let route = Route {
            path: path.to_string(),
            hand_fn: hand,
            method,
        };

        // push route to routes
        self.routes.push(route);
    }

    pub fn all(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("ALL".as_bytes()).unwrap(), hand);
    }

    pub fn get(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::GET, hand);
    }

    pub fn post(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::POST, hand);
    }

    pub fn put(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::PUT, hand);
    }

    pub fn delete(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::DELETE, hand);
    }

    pub fn patch(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::PATCH, hand);
    }

    pub fn copy(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("COPY".as_bytes()).unwrap(), hand);
    }

    pub fn options(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::OPTIONS, hand);
    }

    pub fn link(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("LINK".as_bytes()).unwrap(), hand);
    }

    pub fn unlink(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("UNLINK".as_bytes()).unwrap(), hand);
    }

    pub fn purge(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("PURGE".as_bytes()).unwrap(), hand);
    }

    pub fn lock(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("LOCK".as_bytes()).unwrap(), hand);
    }

    pub fn unlock(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("UNLOCK".as_bytes()).unwrap(), hand);
    }

    pub fn view(&mut self, path: &'static str, hand: HandFn) {
        self.add(path, Method::from_bytes("VIEW".as_bytes()).unwrap(), hand);
    }

    pub fn propfind(&mut self, path: &'static str, hand: HandFn) {
        self.add(
            path,
            Method::from_bytes("PROPFIND".as_bytes()).unwrap(),
            hand,
        );
    }

    // get route
    pub fn find(&self, path: String, method: Method) -> Option<&Route> {
        for route in self.routes.iter() {
            if route.method.clone().as_str() == "ALL" {
                if route.path == path {
                    return Some(route);
                }
            } else {
                if route.path == path && route.method.clone() == method {
                    return Some(route);
                }
            }
        }

        None
    }
}