use http::Method;
use serde::Serialize;
use url::{ParseError, Url};

use crate::response;

pub trait RequestBase {
    fn new(url: &'static str) -> Result<Self, ParseError>
    where
        Self: Sized;
    fn launch(self) -> response::Response;
}

#[derive(Debug)]
pub struct Request {
    pub url: url::Url,
    method: Method,
}

impl RequestBase for Request {
    fn new<'a>(url: &'a str) -> Result<Request, ParseError> {
        match Url::parse(url) {
            Ok(url_parsed) => Ok(Request {
                url: url_parsed,
                method: Method::GET,
            }),
            Err(error) => Err(error),
        }
    }

    fn launch(self) -> response::Response {
        let client = reqwest::blocking::Client::new();
        let resp = (match self.method {
            Method::GET => client.get(self.url.as_str()),
            Method::POST => client.post(self.url.as_str()),
            Method::PUT => client.put(self.url.as_str()),
            Method::PATCH => client.patch(self.url.as_str()),
            Method::DELETE => client.delete(self.url.as_str()),
            _ => unimplemented!(),
        })
        .send()
        .unwrap();

        let status = resp.status();
        let text = resp.text().unwrap();

        let url = self.url.clone();

        response::Response {
            text: text,
            status_code: status,
            url: url,
        }
    }
}

impl Request {
    pub fn method(mut self, method: Method) -> Self {
        self.method = method;
        self
    }

    pub fn add_attrs<T: Serialize + Sized>(self, _attrs: T) -> Self {
        unimplemented!();
    }
}