use std::fs;
use std::collections::HashMap;
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use toml::{self, de::Error};
use crate::phighlighter::PLocation;
use crate::pcontent::{
PContentType, PReferenceUrl, PVecContent
};
use crate::plectureparser::PLectureData;
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
struct LectureCitationConfig{
name: String,
documentation_url: String,
label: HashMap<String, String>,
}
impl LectureCitationConfig {
fn get_reference_url(&self, label_name: &String) -> Option<PReferenceUrl> {
match self.label.get(label_name) {
Some(text) => Some(PReferenceUrl::from_url(&String::from(format!("{}/redirection.html?label={}", self.documentation_url, label_name)), text)),
None => None,
}
}
}
fn load_lecture_ctation_config(filename: &PathBuf) -> Result<LectureCitationConfig, Error> {
let config: LectureCitationConfig = match fs::read_to_string(filename) {
Ok(str) => match toml::from_str(&str){
Ok(value) => value,
Err(error) => panic!("load_lecture_ctation_config : cannot parse file {:?}\n\tParsing error {}", filename, error)
},
Err(err) => panic!("load_lecture_ctation_config : cannot read file {:?}\n\tError: {}", filename, err)
};
Ok(config)
}
#[derive(Debug, Clone, Default)]
pub struct PReferenceManager{
p_map_label: HashMap<String, usize>,
p_map_reference: HashMap<String, PLocation>,
p_map_lecture_reference: HashMap<String, HashMap<String, PLocation>>,
p_map_label_id: HashMap<usize, String>,
p_map_reference_url: HashMap<String, PReferenceUrl>,
p_map_lecture_dependency: HashMap<String, LectureCitationConfig>,
}
impl PReferenceManager{
pub fn load_lecture_dependency(&mut self, lecture_name: &String, dependency_config: &PathBuf){
let config: LectureCitationConfig = match load_lecture_ctation_config(dependency_config) {
Ok(value) => value,
Err(err) => panic!("load_lecture_dependency : cannot load lecture '{}' configuration\n\tIn file {:?}\n\tError {}", lecture_name, dependency_config, err)
};
self.p_map_lecture_dependency.insert(lecture_name.clone(), config.clone());
}
pub fn add_reference(&mut self, data: &PLectureData){
for (name, id) in data.get_map_label().iter(){
self.p_map_label.insert(name.clone(), *id);
}
for (reference_name, reference_location) in data.get_map_reference().iter(){
self.p_map_reference.insert(reference_name.clone(), reference_location.clone());
}
for (lecture_name, map_reference) in data.get_map_lecture_reference().iter(){
for (reference_name, reference_location) in map_reference.iter() {
match self.p_map_lecture_reference.get_mut(lecture_name) {
Some(lecture_ref) => {
lecture_ref.insert(reference_name.clone(), reference_location.clone());
},
None => {
let mut lecture_ref: HashMap<String, PLocation> = Default::default();
lecture_ref.insert(reference_name.clone(), reference_location.clone());
self.p_map_lecture_reference.insert(lecture_name.clone(), lecture_ref.clone());
}
}
}
}
}
pub fn solve_reference(&mut self, vec_content: &mut PVecContent){
println!("PReferenceManager::solve_reference : solving references and labels");
self.build_all_reference(vec_content);
self.build_reference_url(vec_content);
self.update_reference(vec_content);
}
pub fn save_redirection_html(&self, output_dir: &PathBuf){
let mut body = String::from(r#"<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Page redirection</title>
<link rel="stylesheet" href="book/dark.css" />
<script type="text/javascript">
function redirectionWithLabelReference(){
var parameters = location.search.substring(1).split("?");
var tmp = parameters[0].split("=");
referenceName = unescape(tmp[1]);
var dictReference = {
"#);
let mut comma = String::from("");
for (label, url) in self.p_map_reference_url.iter(){
body += &String::from(format!("{}\t\t\t\t\t\"{}\": \"{}\"", comma, label, url.get_url()));
comma = String::from(",\n");
}
body += &String::from(r#"
};
if(referenceName in dictReference){
document.location.href=dictReference[referenceName];
}else{
document.location.href="index.html";
}
}
</script>
</head>
<body onLoad="setTimeout('redirectionWithLabelReference()', 1000)">
<div>In 1 second you will get the page you asked for... normally</div>
</body>
</html>
"#);
let redirection_page: PathBuf = output_dir.join(&PathBuf::from("redirection.html"));
match fs::write(&redirection_page, body) {
Ok(_) => {},
Err(err) => panic!("save_redirection_html : cannot write file {:?}\n\tError {}", redirection_page, err)
};
}
pub fn save_lecture_citation_config(&self, output_dir: &PathBuf, lecture_name: &String, documentation_url: &String){
let dependency_config: PathBuf = output_dir.join(PathBuf::from("lecture_citation.toml"));
let mut lecture_config: LectureCitationConfig = LectureCitationConfig {
name: lecture_name.clone(),
documentation_url: documentation_url.clone(),
label: Default::default()
};
for (label_name, reference) in self.p_map_reference_url.iter(){
lecture_config.label.insert(label_name.clone(), reference.get_simple_text().clone());
}
fs::write(dependency_config, toml::to_string(&lecture_config).unwrap()).unwrap();
}
fn build_all_reference(&mut self, vec_content: &PVecContent){
for content in vec_content.get_vec_child().iter(){
match content {
PContentType::Paragraph(paragraph) => self.build_all_reference(paragraph.get_data().get_content()),
PContentType::ListItem(listitem) => self.build_all_reference(listitem.get_data().get_content()),
PContentType::Environment(environement) => self.build_all_reference(environement.get_data().get_content()),
PContentType::Table(table) => {
for row in table.get_data().get_vec_row().iter() {
for cell in row.get_vec_cell().iter() {
self.build_all_reference(cell.get_content());
}
}
}
other => {
match other.get_label() {
Some(label) => {
if !label.is_empty() {
self.p_map_label_id.insert(other.get_id(), label.clone());
}
},
None => {}
}
}
}
}
}
fn build_reference_url(&mut self, vec_content: &PVecContent){
let mut current_file = String::from("index.html");
self.build_reference_url_sub(vec_content, &mut current_file);
}
fn build_reference_url_sub(&mut self, vec_content: &PVecContent, current_file: &mut String){
for content in vec_content.get_vec_child().iter(){
match content {
PContentType::Title(title) => *current_file = title.get_data().get_output_filename().clone(),
_ => {}, };
match content {
PContentType::Paragraph(paragraph) => self.build_reference_url_sub(paragraph.get_data().get_content(), current_file),
PContentType::ListItem(listitem) => self.build_reference_url_sub(listitem.get_data().get_content(), current_file),
PContentType::Environment(environment) => self.build_reference_url_sub(environment.get_data().get_content(), current_file),
PContentType::Table(table) => {
for row in table.get_data().get_vec_row().iter() {
for cell in row.get_vec_cell().iter() {
self.build_reference_url_sub(cell.get_content(), current_file);
}
}
}
other => {
match self.p_map_label_id.get(&other.get_id()) {
Some(label) => {
self.p_map_reference_url.insert(label.clone(), other.get_reference_url(current_file));
},
None => {}
};
}
}
}
}
fn update_reference(&self, vec_content: &mut PVecContent){
for content in vec_content.get_vec_child_mut().iter_mut(){
match content {
PContentType::Paragraph(paragraph) => self.update_reference(paragraph.get_data_mut().get_content_mut()),
PContentType::ListItem(listitem) => self.update_reference(listitem.get_data_mut().get_content_mut()),
PContentType::Environment(environment) => self.update_reference(environment.get_data_mut().get_content_mut()),
PContentType::Table(table) => {
for row in table.get_data_mut().get_vec_row_mut().iter_mut() {
for cell in row.get_vec_cell_mut().iter_mut() {
self.update_reference(cell.get_content_mut());
}
}
}
PContentType::Reference(reference) => {
let lecture_name = reference.get_data().get_other_lecture_name();
if lecture_name.is_empty(){
match self.p_map_reference_url.get(reference.get_data().get_reference()) {
Some(refurl) => reference.get_data_mut().set_url(refurl),
None => {
panic!("PReferenceManager::update_reference : cannot get the reference '{}'", reference.get_data().get_reference());
} };
}else{
match self.p_map_lecture_dependency.get(lecture_name) {
Some(lecture_map) => {
let label_name = reference.get_data().get_reference();
match lecture_map.get_reference_url(&label_name){
Some(value_ref) => reference.get_data_mut().set_url(&value_ref),
None => panic!("PReferenceManager::update_reference : no reference '{}' in lecture '{}'", label_name, lecture_name)
}
},
None => panic!("PReferenceManager::update_reference : cannot get the lecture '{}' to have reference from", lecture_name)
}
}
},
_ => {} };
}
}
}
#[cfg(test)]
mod tests{
use super::*;
#[test]
fn test_load_lecture_citation_config(){
let citation_config = PathBuf::from("tests/LectureWithDependency/dependencies/performance_with_stencil.toml");
let config: LectureCitationConfig = load_lecture_ctation_config(&citation_config).unwrap();
assert_eq!(config.name, String::from("performance_with_stencil"));
assert_eq!(config.documentation_url, String::from("https://cta-lapp.pages.in2p3.fr/PHOENIX_LIBS2/static-site-generator/RustyPhoenixLecture"));
assert_eq!(config.label.len(), 2);
assert_eq!(config.get_reference_url(&String::from("figTweety")), Some(PReferenceUrl::from_url(&String::from("https://cta-lapp.pages.in2p3.fr/PHOENIX_LIBS2/static-site-generator/RustyPhoenixLecture/redirection.html?label=figTweety"), &String::from("Figure 26"))));
}
}