//! # PhotoBook
//!
//! `PhotoBook` is a command line tool to harvest, organize, download from clouds and backup your photos.
//! `PhotoBook`is packaged with an Elasticsearch database and Kibana as consultation interface.
//!
//! Simply install it from cargo to try it !
//! ```
//! cargo install photobook
//! ```
//!
//! For further information and usage please refer to its repository : https://gitlab.com/slyatwork/photobook
//!


extern crate confy;
#[macro_use]
extern crate error_chain;
extern crate reqwest;

use chrono::Utc;
use structopt::StructOpt;

use crate::cli::Cli;
use crate::errors::*;
use crate::processors::download_processor::DownloadProcessor;
use crate::processors::harvest_processor::HarvestProcessor;
use crate::processors::processor::Processor;
use crate::services::es_client::ElasticClient;

pub mod constants;

pub mod cli;
pub mod config;

pub mod models {
    pub mod picture;
    pub mod flickr_photo;
    pub mod photo;
}

pub mod helpers { pub mod es_helper; }

pub mod harvest {
    pub mod filesystem_harvester;
    pub mod flickr_harvester;
    pub mod harvester;
}

pub mod download {
    pub mod downloader;
    pub mod flickr_downloader;
}

pub mod services {
    pub mod es_client;
    pub mod filesystem_reader;
    pub mod flickr_client;
}

pub mod processors {
    pub mod processor;
    pub mod harvest_processor;
    pub mod download_processor;
    pub mod report;
}

pub mod errors {
    error_chain! {
        foreign_links {
            Io(std::io::Error);
            HttpRequest(reqwest::Error);
            Config(confy::ConfyError);
        }
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    if is_elastic_running().await {
        println!("{} - CLI process started", Utc::now().format("%Y-%m-%d %H:%M:%S"));

        let args = Cli::from_args();
        println!("Process launched for {:?}", &args);
        match args {
            Cli::Harvest { source, operation, path } => {
                let processor = HarvestProcessor::new(source, operation, path);
                match processor.process().await {
                    Ok(n) => println!("harvest report : {:?}", n),
                    Err(n) => println!("{:?} errors occurred", n)
                };
            }
            Cli::Organize { from, to } => println!("{:?} - {:?}\nSorry, Organize process is not implemented at this time", from, to),
            Cli::Download { source, to, server } => {
                let processor = DownloadProcessor::new(source, to, server);
                match processor.process().await {
                    Ok(n) => println!("download report : {:?}", n),
                    Err(n) => println!("{:?} errors occurred", n)
                };
            }
            Cli::Backup { from, to } => println!("{:?} - {:?}\nSorry, Organize process is not implemented at this time", from, to),
        }
        println!("{} - CLI process ended", Utc::now().format("%Y-%m-%d %H:%M:%S"));
    } else {
        println!("It seems elasticsearch is not running yet !\n\
        - if you use a distant server, please verify its accessibility and your config\n\
        - if you use a local docker stack, check the dockers are well launched\n  \
          *remember* type 'docker-compose down && docker-compose up -d' where the docker-compose.yml provided lands.")
    }
    Ok(())
}

async fn is_elastic_running() -> bool {
    let client = ElasticClient::new("");
    match client.get_indices().await {
        Ok(indices) => indices.len() > 0,
        Err(_) => false
    }
}
