<commit_before>extern crate handlebars;
extern crate rustc_serialize;

use std::path::{PathBuf, Path};
use std::collections::BTreeMap;

use self::rustc_serialize::json::{self, ToJson};
use self::handlebars::{Handlebars, RenderError, RenderContext, Helper, Context, Renderable};

// Handlebars helper for navigation

pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    debug!("[fn]: previous (handlebars helper)");

    debug!("[*]: Get data from context");
    // get value from context data
    // rc.get_path() is current json parent path, you should always use it like this
    // param is the key of value you want to display
    let chapters = c.navigate(rc.get_path(), "chapters");

    let current = c.navigate(rc.get_path(), "path")
        .to_string()
        .replace("\"", "");

    let path_to_root = PathBuf::from(
        c.navigate(rc.get_path(), "path_to_root")
            .to_string()
            .replace("\"", "")
    );

    debug!("[*]: Decode chapters from JSON");
    // Decode json format
    let decoded: Vec<BTreeMap<String, String>> = match json::decode(&chapters.to_string()) {
        Ok(data) => data,
        Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}),
    };
    let mut previous: Option<BTreeMap<String, String>> = None;


    debug!("[*]: Search for current Chapter");
    // Search for current chapter and return previous entry
    for item in decoded {

        match item.get("path") {
            Some(path) if path.len() > 0 => {
                if path == &current {

                    debug!("[*]: Found current chapter");
                    if let Some(previous) = previous{

                        debug!("[*]: Creating BTreeMap to inject in context");
                        // Create new BTreeMap to extend the context: 'title' and 'link'
                        let mut previous_chapter = BTreeMap::new();

                        // Chapter title
                        match previous.get("name") {
                            Some(n) => {
                                debug!("[*]: Inserting title: {}", n);
                                previous_chapter.insert("title".to_string(), n.to_json())
                            },
                            None => {
                                debug!("[*]: No title found for chapter");
                                return Err(RenderError{ desc: "No title found for chapter in JSON data" })
                            }
                        };

                        // Chapter link

                        match previous.get("path") {
                            Some(p) => {
                                let path = path_to_root.join(Path::new(p).with_extension("html"));
                                debug!("[*]: Inserting link: {:?}", path);

                                match path.to_str() {
                                    Some(p) => { previous_chapter.insert("link".to_string(), p.to_json()); },
                                    None => return Err(RenderError{ desc: "Link could not be converted to str" })
                                }
                            },
                            None => return Err(RenderError{ desc: "No path found for chapter in JSON data" })
                        }

                        debug!("[*]: Inject in context");
                        // Inject in current context
                        let updated_context = c.extend(&previous_chapter);

                        debug!("[*]: Render template");
                        // Render template
                        match _h.template() {
                            Some(t) => {
                                try!(t.render(&updated_context, r, rc));
                            },
                            None => return Err(RenderError{ desc: "Error with the handlebars template" })
                        }

                    }

                    break;
                }
                else {
                    previous = Some(item.clone());
                }
            },
            _ => continue,

        }

    }

    Ok(())
}




pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    debug!("[fn]: next (handlebars helper)");

    debug!("[*]: Get data from context");
    // get value from context data
    // rc.get_path() is current json parent path, you should always use it like this
    // param is the key of value you want to display
    let chapters = c.navigate(rc.get_path(), "chapters");

    let current = c.navigate(rc.get_path(), "path")
        .to_string()
        .replace("\"", "");

    let path_to_root = PathBuf::from(
        c.navigate(rc.get_path(), "path_to_root")
            .to_string()
            .replace("\"", "")
    );

    debug!("[*]: Decode chapters from JSON");
    // Decode json format
    let decoded: Vec<BTreeMap<String, String>> = match json::decode(&chapters.to_string()) {
        Ok(data) => data,
        Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}),
    };
    let mut previous: Option<BTreeMap<String, String>> = None;

    debug!("[*]: Search for current Chapter");
    // Search for current chapter and return previous entry
    for item in decoded {

        match item.get("path") {

            Some(path) if path.len() > 0 => {

                if let Some(previous) = previous {

                    let path = match previous.get("path") {
                        Some(p) => p,
                        None => return Err(RenderError{ desc: "No path found for chapter in JSON data"})
                    };

                    if path == &current {

                        debug!("[*]: Found current chapter");
                        debug!("[*]: Creating BTreeMap to inject in context");
                        // Create new BTreeMap to extend the context: 'title' and 'link'
                        let mut next_chapter = BTreeMap::new();

                        match item.get("name") {
                            Some(n) => {
                                debug!("[*]: Inserting title: {}", n);
                                next_chapter.insert("title".to_string(), n.to_json());
                            }
                            None => return Err(RenderError{ desc: "No title found for chapter in JSON data"})
                        }

                        let link = path_to_root.join(Path::new(path).with_extension("html"));
                        debug!("[*]: Inserting link: {:?}", link);

                        match link.to_str() {
                            Some(l) => { next_chapter.insert("link".to_string(), l.to_json()); },
                            None => return Err(RenderError{ desc: "Link could not converted to str"})
                        }

                        debug!("[*]: Inject in context");
                        // Inject in current context
                        let updated_context = c.extend(&next_chapter);

                        debug!("[*]: Render template");

                        // Render template
                        match _h.template() {
                            Some(t) => {
                                try!(t.render(&updated_context, r, rc));
                            },
                            None => return Err(RenderError{ desc: "Error with the handlebars template" })
                        }

                        break
                    }
                }

                previous = Some(item.clone());
            },

            _ => continue,<commit_msg>Fix #40 where next helper returned a link to the current chapter instead of the next<commit_after>extern crate handlebars;
extern crate rustc_serialize;

use std::path::{PathBuf, Path};
use std::collections::BTreeMap;

use self::rustc_serialize::json::{self, ToJson};
use self::handlebars::{Handlebars, RenderError, RenderContext, Helper, Context, Renderable};

// Handlebars helper for navigation

pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    debug!("[fn]: previous (handlebars helper)");

    debug!("[*]: Get data from context");
    // get value from context data
    // rc.get_path() is current json parent path, you should always use it like this
    // param is the key of value you want to display
    let chapters = c.navigate(rc.get_path(), "chapters");

    let current = c.navigate(rc.get_path(), "path")
        .to_string()
        .replace("\"", "");

    let path_to_root = PathBuf::from(
        c.navigate(rc.get_path(), "path_to_root")
            .to_string()
            .replace("\"", "")
    );

    debug!("[*]: Decode chapters from JSON");
    // Decode json format
    let decoded: Vec<BTreeMap<String, String>> = match json::decode(&chapters.to_string()) {
        Ok(data) => data,
        Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}),
    };
    let mut previous: Option<BTreeMap<String, String>> = None;


    debug!("[*]: Search for current Chapter");
    // Search for current chapter and return previous entry
    for item in decoded {

        match item.get("path") {
            Some(path) if path.len() > 0 => {
                if path == &current {

                    debug!("[*]: Found current chapter");
                    if let Some(previous) = previous{

                        debug!("[*]: Creating BTreeMap to inject in context");
                        // Create new BTreeMap to extend the context: 'title' and 'link'
                        let mut previous_chapter = BTreeMap::new();

                        // Chapter title
                        match previous.get("name") {
                            Some(n) => {
                                debug!("[*]: Inserting title: {}", n);
                                previous_chapter.insert("title".to_string(), n.to_json())
                            },
                            None => {
                                debug!("[*]: No title found for chapter");
                                return Err(RenderError{ desc: "No title found for chapter in JSON data" })
                            }
                        };

                        // Chapter link

                        match previous.get("path") {
                            Some(p) => {
                                let path = path_to_root.join(Path::new(p).with_extension("html"));
                                debug!("[*]: Inserting link: {:?}", path);

                                match path.to_str() {
                                    Some(p) => { previous_chapter.insert("link".to_string(), p.to_json()); },
                                    None => return Err(RenderError{ desc: "Link could not be converted to str" })
                                }
                            },
                            None => return Err(RenderError{ desc: "No path found for chapter in JSON data" })
                        }

                        debug!("[*]: Inject in context");
                        // Inject in current context
                        let updated_context = c.extend(&previous_chapter);

                        debug!("[*]: Render template");
                        // Render template
                        match _h.template() {
                            Some(t) => {
                                try!(t.render(&updated_context, r, rc));
                            },
                            None => return Err(RenderError{ desc: "Error with the handlebars template" })
                        }

                    }

                    break;
                }
                else {
                    previous = Some(item.clone());
                }
            },
            _ => continue,

        }

    }

    Ok(())
}




pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    debug!("[fn]: next (handlebars helper)");

    debug!("[*]: Get data from context");
    // get value from context data
    // rc.get_path() is current json parent path, you should always use it like this
    // param is the key of value you want to display
    let chapters = c.navigate(rc.get_path(), "chapters");

    let current = c.navigate(rc.get_path(), "path")
        .to_string()
        .replace("\"", "");

    let path_to_root = PathBuf::from(
        c.navigate(rc.get_path(), "path_to_root")
            .to_string()
            .replace("\"", "")
    );

    debug!("[*]: Decode chapters from JSON");
    // Decode json format
    let decoded: Vec<BTreeMap<String, String>> = match json::decode(&chapters.to_string()) {
        Ok(data) => data,
        Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}),
    };
    let mut previous: Option<BTreeMap<String, String>> = None;

    debug!("[*]: Search for current Chapter");
    // Search for current chapter and return previous entry
    for item in decoded {

        match item.get("path") {

            Some(path) if path.len() > 0 => {

                if let Some(previous) = previous {

                    let previous_path = match previous.get("path") {
                        Some(p) => p,
                        None => return Err(RenderError{ desc: "No path found for chapter in JSON data"})
                    };

                    if previous_path == &current {

                        debug!("[*]: Found current chapter");
                        debug!("[*]: Creating BTreeMap to inject in context");
                        // Create new BTreeMap to extend the context: 'title' and 'link'
                        let mut next_chapter = BTreeMap::new();

                        match item.get("name") {
                            Some(n) => {
                                debug!("[*]: Inserting title: {}", n);
                                next_chapter.insert("title".to_string(), n.to_json());
                            }
                            None => return Err(RenderError{ desc: "No title found for chapter in JSON data"})
                        }


                        let link = path_to_root.join(Path::new(path).with_extension("html"));
                        debug!("[*]: Inserting link: {:?}", link);

                        match link.to_str() {
                            Some(l) => { next_chapter.insert("link".to_string(), l.to_json()); },
                            None => return Err(RenderError{ desc: "Link could not converted to str"})
                        }

                        debug!("[*]: Inject in context");
                        // Inject in current context
                        let updated_context = c.extend(&next_chapter);

                        debug!("[*]: Render template");

                        // Render template
                        match _h.template() {
                            Some(t) => {
                                try!(t.render(&updated_context, r, rc));
                            },
                            None => return Err(RenderError{ desc: "Error with the handlebars template" })
                        }

                        break
                    }
                }

                previous = Some(item.clone());
            },

            _ => continue,
{'fraction_non_alphanumeric': 0.1253879979306777, 'fraction_numerical': 0.00038799793067770304, 'mean_word_length': 1.3280144513021226, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '366203', 'n_tokens_mistral': 3907, 'n_tokens_neox': 3680, 'n_words': 1084}