use std::fs;
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
use crate::{
lecture_config::LectureConfig,
phighlighter::{PFileParser, PLocation},
plectureparser::{
PReferenceManager,
PAbstractContent, PAbstractLectureBackend,
PLectureParser, PLectureData, PLecureBackend,
PContentTitle, PContentType, PVecContent,
PRessourceArchive,
PLabelId,
phoenix_html_404
}
};
pub struct PLecture{
p_config: LectureConfig,
p_output_path: PathBuf,
p_base_theme_page: String,
p_content: PVecContent,
p_reference_manager: PReferenceManager,
p_first_next_page: String,
p_map_archive: HashMap<PathBuf, PRessourceArchive>,
}
pub fn create_lecture_website(config: &LectureConfig, output_path: &PathBuf){
let mut lecture = PLecture::new(config, output_path);
lecture.load();
}
impl PLecture{
fn new(config: &LectureConfig, output_path: &PathBuf) -> Self{
let mut other = PLecture {
p_config: config.clone(),
p_output_path: output_path.canonicalize().unwrap(),
p_base_theme_page: Default::default(),
p_content: Default::default(),
p_reference_manager: Default::default(),
p_first_next_page: String::from(""),
p_map_archive: Default::default(),
};
let theme_file: PathBuf = other.p_config.get_theme_path().join("theme.html");
other.p_base_theme_page = match fs::read_to_string(&theme_file) {
Ok(str) => str,
Err(err) => panic!("PLecture::new : cannot load theme at {:?}. Error {}", theme_file, err)
};
other.load_dependency();
return other;
}
fn load_dependency(&mut self){
if self.p_config.get_map_dependency().len() == 0 {
return;
}
let dependency_config_dir: PathBuf = PathBuf::from("dependencies");
if !dependency_config_dir.exists() {
match fs::create_dir_all(&dependency_config_dir) {
Ok(_) => {},
Err(err) => panic!("PLecture::load_dependency : cannot create dependency directory {:?}\n\tError {}", dependency_config_dir, err)
}
}
for (name, url) in self.p_config.get_map_dependency().iter(){
let dependency_config: PathBuf = dependency_config_dir.join(PathBuf::from(format!("{}.toml", name)));
if !dependency_config.exists() {
match Command::new("wget").arg("-O").arg(&dependency_config).arg(format!("{}/lecture_citation.toml",url)).output() {
Ok(output) => {
if !output.status.success() {
panic!("PLecture::load_dependency : cannot get the lecture dependency '{}'\n\tfrom url '{}'\n\tMaybe the url does not exist or there is no internet", name, url)
}
},
Err(err) => panic!("PLecture::load_dependency : cannot call wget to get the lecture dependency '{}'\n\tfrom url '{}'\n\tError {}", name, url, err)
}
}
self.p_reference_manager.load_lecture_dependency(name, &dependency_config);
}
}
fn load(&mut self){
println!("PLecture::load : loading lecture files");
self.save_theme();
let lecture_parser = PLectureParser::new(&self.p_output_path, self.p_config.get_vec_parser(), self.p_config.get_vec_environment());
for input_file in self.p_config.get_vec_file().iter(){
let parser: PFileParser = PFileParser::from_file(input_file);
let mut data = PLectureData::new(0, &parser);
if ! lecture_parser.parse(&mut self.p_content, &mut data) {
panic!("PLecture::load : cannot parse the file {:?}", parser.get_filename());
}
self.p_reference_manager.add_reference(&data);
for (output_path, archive) in data.get_map_archive().iter(){
self.p_map_archive.insert(output_path.clone(), archive.clone());
}
}
self.update_title_number();
self.update_prev_next_section();
self.p_reference_manager.solve_reference(&mut self.p_content);
self.save_website();
self.create_all_archive();
}
fn update_title_number(&mut self){
println!("PLecture::update_title_number : updating title number");
let mut vec_title_number: Vec<usize> = vec![];
self.p_content.update_title_number(&mut vec_title_number);
}
fn update_prev_next_section(&mut self){
println!("PLecture::update_prev_next_section : updating previous and next section");
let mut prev_page = String::from("index.html");
let mut prev_section: Option<&mut PContentTitle> = None;
for content in self.p_content.get_vec_child_mut().iter_mut() {
match content {
PContentType::Title(section) => {
match prev_section {
Some(prev) => prev.set_next_filename(section.get_data().get_output_filename()),
None => {}
};
section.get_data_mut().set_previous_filename(&prev_page);
prev_page = section.get_data().get_output_filename().clone();
prev_section = Some(section.get_data_mut());
if self.p_first_next_page.is_empty() {
self.p_first_next_page = prev_page.clone();
}
},
&mut _ => {}
};
}
match prev_section {
Some(prev) => prev.set_next_filename(&prev.get_output_filename().clone()),
None => {}
};
}
fn create_output_path(&self){
match fs::create_dir_all(&self.p_output_path){
Ok(_) => {},
Err(err) => panic!("PLecture::create_output_path : cannot create output directory {:?}. Error {}", self.p_output_path, err)
};
}
fn save_theme(&self){
println!("PLecture::save_theme : saving theme");
self.create_output_path();
Command::new("cp")
.arg("-r")
.arg(self.p_config.get_theme_path())
.arg(&self.p_output_path)
.spawn().expect("PLecture::save_website : Cannot copy theme into output directory");
}
fn save_website(&self){
println!("PLecture::save_website : saving website");
let current_branch = String::from("main"); let mut backend = PLecureBackend::new(&self.p_output_path, &self.p_config.get_project_url(), &self.p_config.get_contact_mail(), ¤t_branch, &self.p_config.get_master_project(), &self.p_content);
let first_lecture_source: String = self.get_first_source_file();
backend.create_file(&String::from(self.p_output_path.join("index.html").to_str().unwrap()), &self.p_config.get_title(),
&PLocation::new(&PathBuf::from(first_lecture_source), 1, 1), &String::from("index.html"), &self.p_first_next_page);
self.create_main_page(&mut backend);
self.p_content.to_html(&mut backend, &PLabelId::new(0));
phoenix_html_404(&self.p_output_path);
self.p_reference_manager.save_redirection_html(&self.p_output_path);
self.p_reference_manager.save_lecture_citation_config(&self.p_output_path, &self.p_config.get_name(), &self.p_config.get_documentation_url());
}
fn create_main_page(&self, backend: &mut PLecureBackend){
backend.write(&format!("<h1 class=\"mainTitle\">{}</h1>\n", self.p_config.get_title()));
backend.write(&String::from("<h5 class=\"author\">"));
let mut comma = String::from("");
for author in self.p_config.get_vec_author().iter(){
backend.write(&format!("{}{}",comma, author));
comma = String::from(", ");
}
backend.write(&String::from("</h5>\n"));
}
fn get_first_source_file(&self) -> String {
match self.p_config.get_vec_file().get(0) {
Some(filename) => String::from(filename.join(&self.p_output_path).to_str().unwrap()),
None => String::from("index.md")
}
}
fn create_all_archive(&self){
println!("PLecture::create_all_archive : creating {} archives of the lecture", self.p_map_archive.len());
for (_, archive) in self.p_map_archive.iter(){
archive.create_archive();
}
}
}