use async_std::task;
use async_trait::async_trait;
use medina::{Crawler, CrawlerRunner, Error, Page, PageResult};

pub struct RootPage {
    pub url: String,
}
pub struct FakePage {
    pub url: String,
}

#[async_trait]
impl Page for RootPage {
    async fn process_request(
        &self,
    ) -> Result<(Vec<Box<dyn Page>>, Vec<Box<dyn PageResult>>), Error> {
        let mut vec: Vec<Box<dyn Page>> = Vec::with_capacity(50 * 26);

        for ch in b'a'..(b'z' + 1) {
            for i in 1..50 + 1 {
                vec.push(Box::new(FakePage {
                    url: format!("https://{}.com/{}", ch as char, i),
                }));
            }
        }

        return Ok((vec, Vec::new()));
    }

    fn get_url(&self) -> &String {
        return &self.url;
    }
}

#[async_trait]
impl Page for FakePage {
    async fn process_request(
        &self,
    ) -> Result<(Vec<Box<dyn Page>>, Vec<Box<dyn PageResult>>), Error> {
        return Ok((Vec::new(), Vec::new()));
    }

    fn get_url(&self) -> &String {
        return &self.url;
    }
}

fn main() {
    task::block_on(async {
        let crawler = Crawler::with_capacity(50 * 26, 1.0 / (50.0 * 26.0))
            .set_default_request_rate(5.0)
            .push_item(Box::new(RootPage {
                url: "https://root.com".to_string(),
            }));

        CrawlerRunner::new(crawler)
            .set_crawling_concurrency(50)
            .set_processing_concurrency(30)
            .spawn()
            .await;
    })
}
