// Copyright 2019 The Fuchsia Authors. All rights reserved.
// // Use of this source code is governed by a BSD-style license that can be
// // found in the LICENSE file.
use {
    anyhow::Error,
    diagnostics_data::InspectData,
    diagnostics_hierarchy::{self, DiagnosticsHierarchy, InspectHierarchyMatcher, Property},
    difference::{
        self,
        Difference::{Add, Rem, Same},
    },
    fidl_fuchsia_diagnostics::Selector,
    selectors,
    std::cmp::{max, min},
    std::collections::HashSet,
    std::convert::TryInto,
    std::fs::read_to_string,
    std::io::{stdin, stdout, Write},
    std::path::PathBuf,
    std::sync::Arc,
    structopt::StructOpt,
    termion::{
        cursor,
        event::{Event, Key},
        input::TermRead,
        raw::IntoRawMode,
    },
};

#[derive(Debug, StructOpt)]
struct Options {
    #[structopt(short, long, help = "Inspect JSON file to read")]
    snapshot: String,

    #[structopt(subcommand)]
    command: Command,
}

#[derive(Debug, StructOpt)]
enum Command {
    #[structopt(name = "generate")]
    Generate {
        #[structopt(
            short,
            name = "component",
            help = "Generate selectors for only this component"
        )]
        component_name: Option<String>,
        #[structopt(help = "The output file to generate")]
        selector_file: String,
    },
    #[structopt(name = "apply")]
    Apply {
        #[structopt(
            short,
            name = "component",
            help = "Apply selectors from the provided selector_file for only this component"
        )]
        component_name: Option<String>,
        #[structopt(help = "The selector file to apply to the snapshot")]
        selector_file: String,
    },
}

#[derive(Debug)]
struct Line {
    value: String,
    removed: bool,
}

impl Line {
    fn new(s: impl ToString) -> Self {
        Self { value: s.to_string(), removed: false }
    }

    fn removed(s: impl ToString) -> Self {
        Self { value: s.to_string(), removed: true }
    }

    fn len(&self) -> usize {
        self.value.len()
    }
}

struct Output {
    lines: Vec<Line>,
    offset_top: usize,
    offset_left: usize,
    max_line_len: usize,

    filter_removed: bool,
}

impl Output {
    fn new(lines: Vec<Line>) -> Self {
        let max_line_len = lines.iter().map(|l| l.len()).max().unwrap_or(0);
        Output { lines, offset_top: 0, offset_left: 0, max_line_len, filter_removed: false }
    }

    fn set_lines(&mut self, lines: Vec<Line>) {
        self.max_line_len = lines.iter().map(|l| l.len()).max().unwrap_or(0);
        self.lines = lines;
        self.scroll(0, 0);
    }

    fn max_lines() -> i64 {
        let (_, h) = termion::terminal_size().unwrap();
        h as i64 - 2 // Leave 2 lines for info.
    }

    fn refresh(&self, stdout: &mut impl Write) {
        let (w, h) = termion::terminal_size().unwrap();
        let max_lines = Output::max_lines() as usize;

        self.lines
            .iter()
            .filter(|l| !self.filter_removed || !l.removed)
            .skip(self.offset_top)
            .take(max_lines)
            .enumerate()
            .for_each(|(i, line)| {
                if self.offset_left >= line.value.len() {
                    return;
                }
                let end = min(line.value.len(), self.offset_left + w as usize);

                if line.removed {
                    write!(stdout, "{}", termion::color::Fg(termion::color::Red)).unwrap();
                }
                write!(
                    stdout,
                    "{}{}{}",
                    termion::cursor::Goto(1, (i + 1) as u16),
                    line.value[self.offset_left..end].to_string(),
                    termion::color::Fg(termion::color::Reset),
                )
                .unwrap();
            });

        write!(
            stdout,
            "{}------------------- T: {}/{}, L: {}/{}{}Controls: [Q]uit. [R]efresh. {} filtered data. Arrow keys scroll.",
            termion::cursor::Goto(1, h - 1),
            self.offset_top, self.visible_line_count(), self.offset_left, self.max_line_len,
            termion::cursor::Goto(1, h),
            if self.filter_removed { "S[h]ow" } else { "[H]ide" },
        )
        .unwrap();
    }

    fn visible_line_count(&self) -> usize {
        self.lines.iter().filter(|l| !self.filter_removed || !l.removed).count()
    }

    fn scroll(&mut self, down: i64, right: i64) {
        let (w, h) = termion::terminal_size().unwrap();
        self.offset_top = max(0, self.offset_top as i64 + down) as usize;
        self.offset_left = max(0, self.offset_left as i64 + right) as usize;
        self.offset_top =
            min(self.offset_top as i64, max(0, self.visible_line_count() as i64 - h as i64))
                as usize;
        self.offset_left =
            min(self.offset_left as i64, max(0, self.max_line_len as i64 - w as i64)) as usize;
    }

    fn set_filter_removed(&mut self, val: bool) {
        if self.filter_removed == val {
            return;
        }

        self.filter_removed = val;

        if self.filter_removed {
            // Starting to filter, tweak offset_top to remove offsets from newly filtered lines.
            self.offset_top -= self.lines.iter().take(self.offset_top).filter(|l| l.removed).count()
        } else {
            // TODO: Fix this
        }
    }
}

fn filter_json_schema_by_selectors(
    mut schema: InspectData,
    selector_vec: &Vec<Arc<Selector>>,
) -> Option<InspectData> {
    // A failure here implies a malformed snapshot. We want to panic.
    let moniker = selectors::parse_path_to_moniker(&schema.moniker)
        .expect("Snapshot contained an unparsable path.");

    if schema.payload.is_none() {
        schema.payload = Some(DiagnosticsHierarchy::new(
            "root",
            vec![Property::String(
                "filter error".to_string(),
                format!("Node hierarchy was missing for {}", schema.moniker),
            )],
            vec![],
        ));
        return Some(schema);
    }
    let hierarchy = schema.payload.unwrap();

    match selectors::match_component_moniker_against_selectors(&moniker, &selector_vec) {
        Ok(matched_selectors) => {
            if matched_selectors.is_empty() {
                return None;
            }

            let inspect_matcher: InspectHierarchyMatcher = (&matched_selectors).try_into().unwrap();

            match diagnostics_hierarchy::filter_hierarchy(hierarchy, &inspect_matcher) {
                Ok(Some(filtered)) => {
                    schema.payload = Some(filtered);
                    Some(schema)
                }
                Ok(None) => {
                    // Ok(None) implies the tree was fully filtered. This means that
                    // it genuinely should not be included in the output.
                    None
                }
                Err(e) => {
                    schema.payload = Some(DiagnosticsHierarchy::new(
                        "root",
                        vec![Property::String(
                            "filter error".to_string(),
                            format!(
                                "Filtering the hierarchy of {}, an error occurred: {:?}",
                                schema.moniker, e
                            ),
                        )],
                        vec![],
                    ));
                    Some(schema)
                }
            }
        }
        Err(e) => {
            schema.payload = Some(DiagnosticsHierarchy::new(
                "root",
                vec![Property::String(
                    "filter error".to_string(),
                    format!(
                        "Evaulating selectors for {} met an unexpected error condition: {:?}",
                        schema.moniker, e
                    ),
                )],
                vec![],
            ));
            Some(schema)
        }
    }
}

/// Consumes a file containing Inspect selectors and applies them to an array of node hierarchies
/// which had previously been serialized to their json schema.
///
/// Returns a vector of Line printed diffs between the unfiltered and filtered hierarchies,
/// or an Error.
fn filter_data_to_lines(
    selector_file: &str,
    data: &[InspectData],
    requested_name_opt: &Option<String>,
) -> Result<Vec<Line>, Error> {
    let selector_vec: Vec<Arc<Selector>> =
        selectors::parse_selector_file(&PathBuf::from(selector_file))?
            .into_iter()
            .map(Arc::new)
            .collect();

    // Filter the source data that we diff against to only contain the component
    // of interest.
    let mut diffable_source: Vec<InspectData> = match requested_name_opt {
        Some(requested_name) => data
            .into_iter()
            .cloned()
            .filter(|schema| {
                let moniker = selectors::parse_path_to_moniker(&schema.moniker)
                    .expect("Snapshot contained an unparsable path.");
                let component_name = moniker
                    .last()
                    .expect("Monikers in provided data dumps are required to be non-empty.");
                requested_name == component_name
            })
            .collect(),
        None => data.to_vec(),
    };

    let mut filtered_node_hierarchies: Vec<InspectData> = diffable_source
        .clone()
        .into_iter()
        .filter_map(|schema| filter_json_schema_by_selectors(schema, &selector_vec))
        .collect();

    let moniker_cmp = |a: &InspectData, b: &InspectData| {
        a.moniker.partial_cmp(&b.moniker).expect("schema comparison")
    };

    diffable_source.sort_by(moniker_cmp);
    filtered_node_hierarchies.sort_by(moniker_cmp);

    let sort_payload = |schema: &mut InspectData| match &mut schema.payload {
        Some(payload) => {
            payload.sort();
        }
        _ => {}
    };

    diffable_source.iter_mut().for_each(sort_payload);
    filtered_node_hierarchies.iter_mut().for_each(sort_payload);

    let orig_str = serde_json::to_string_pretty(&diffable_source).unwrap();
    let new_str = serde_json::to_string_pretty(&filtered_node_hierarchies).unwrap();
    let cs = difference::Changeset::new(&orig_str, &new_str, "\n");

    // "Added" lines only appear when a property that was once in the middle of a
    // nested object, and thus ended its line with a comma, becomes the final property
    // in a node and thus loses the comma. The difference library doesn't expose edit distance
    // per-line, so we must instead track these "added" lines, and check if any of the "removed"
    // lines are one of the "added" lines with a comma on the end.
    let added_line_tracker: HashSet<&str> =
        cs.diffs.iter().fold(HashSet::new(), |mut acc, change| {
            if let Add(val) = change {
                acc.insert(val);
            }
            acc
        });

    Ok(cs
        .diffs
        .iter()
        .map(|change| match change {
            Same(val) | Add(val) => val.split("\n").map(|l| Line::new(l)).collect::<Vec<Line>>(),
            Rem(val) => val
                .split("\n")
                .filter_map(|l| {
                    let last_char_truncated: &str = &l[..l.len() - 1];
                    if !added_line_tracker.contains(last_char_truncated) {
                        Some(Line::removed(l))
                    } else {
                        None
                    }
                })
                .collect::<Vec<Line>>(),
        })
        .flatten()
        .collect())
}

fn generate_selectors<'a>(
    data: Vec<InspectData>,
    component_name: Option<String>,
) -> Result<String, Error> {
    struct MatchedHierarchy {
        moniker: Vec<String>,
        hierarchy: DiagnosticsHierarchy,
    }

    let matching_hierarchies: Vec<MatchedHierarchy> = data
        .into_iter()
        .filter_map(|schema| {
            let moniker = selectors::parse_path_to_moniker(&schema.moniker)
                .expect("Snapshot contained an unparsable moniker.");

            let component_name_matches = component_name.is_none()
                || component_name.as_ref().unwrap()
                    == moniker
                        .last()
                        .expect("Monikers in provided data dumps are required to be non-empty.");

            schema.payload.and_then(|hierarchy| {
                if component_name_matches {
                    Some(MatchedHierarchy { moniker, hierarchy })
                } else {
                    None
                }
            })
        })
        .collect();

    let mut output: Vec<String> = vec![];

    for matching_hierarchy in matching_hierarchies {
        let sanitized_moniker = matching_hierarchy
            .moniker
            .iter()
            .map(|s| selectors::sanitize_string_for_selectors(s))
            .collect::<Vec<String>>()
            .join("/");

        for (node_path, property_opt) in matching_hierarchy.hierarchy.property_iter() {
            match property_opt {
                Some(property) => {
                    let formatted_node_path = node_path
                        .iter()
                        .map(|s| selectors::sanitize_string_for_selectors(s))
                        .collect::<Vec<String>>()
                        .join("/");
                    let sanitized_property =
                        selectors::sanitize_string_for_selectors(property.name());
                    output.push(format!(
                        "{}:{}:{}",
                        sanitized_moniker.clone(),
                        formatted_node_path,
                        sanitized_property
                    ));
                }
                None => {
                    continue;
                }
            }
        }
    }

    // DiagnosticsHierarchy has an intentionally non-deterministic iteration order, but for client
    // facing tools we'll want to sort the outputs.
    output.sort();

    Ok(output.join("\n"))
}

fn interactive_apply(
    data: Vec<InspectData>,
    selector_file: &str,
    component_name: Option<String>,
) -> Result<(), Error> {
    let stdin = stdin();
    let mut stdout = stdout().into_raw_mode().unwrap();

    let mut output = Output::new(filter_data_to_lines(&selector_file, &data, &component_name)?);

    write!(stdout, "{}{}{}", cursor::Restore, cursor::Hide, termion::clear::All).unwrap();

    output.refresh(&mut stdout);

    stdout.flush().unwrap();

    for c in stdin.events() {
        let evt = c.unwrap();
        match evt {
            Event::Key(Key::Char('q')) => break,
            Event::Key(Key::Char('h')) => output.set_filter_removed(!output.filter_removed),
            Event::Key(Key::Char('r')) => {
                output.set_lines(vec![Line::new("Refreshing filtered hierarchies...")]);
                write!(stdout, "{}", termion::clear::All).unwrap();
                output.refresh(&mut stdout);
                stdout.flush().unwrap();

                output.set_lines(filter_data_to_lines(&selector_file, &data, &component_name)?)
            }
            Event::Key(Key::PageUp) => {
                output.scroll(-Output::max_lines(), 0);
            }
            Event::Key(Key::PageDown) => {
                output.scroll(Output::max_lines(), 0);
            }
            Event::Key(Key::Up) => {
                output.scroll(-1, 0);
            }
            Event::Key(Key::Down) => {
                output.scroll(1, 0);
            }
            Event::Key(Key::Left) => {
                output.scroll(0, -1);
            }
            Event::Key(Key::Right) => {
                output.scroll(0, 1);
            }
            e => {
                println!("{:?}", e);
            }
        }
        write!(stdout, "{}", termion::clear::All).unwrap();
        output.refresh(&mut stdout);
        stdout.flush().unwrap();
    }

    write!(stdout, "{}{}{}", cursor::Restore, cursor::Show, termion::clear::All,).unwrap();
    stdout.flush().unwrap();

    Ok(())
}

fn main() -> Result<(), Error> {
    let opts = Options::from_args();

    let filename = &opts.snapshot;

    let data: Vec<InspectData> = serde_json::from_str(
        &read_to_string(filename).expect(&format!("Failed to read {} ", filename)),
    )
    .expect(&format!("Failed to parse {} as JSON", filename));

    match opts.command {
        Command::Generate { selector_file, component_name } => {
            std::fs::write(
                &selector_file,
                generate_selectors(data, component_name)
                    .expect(&format!("failed to generate selectors")),
            )?;
        }
        Command::Apply { selector_file, component_name } => {
            interactive_apply(data, &selector_file, component_name)?;
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempfile;

    #[test]
    fn generate_selectors_test() {
        let schemas: Vec<InspectData> =
            serde_json::from_value(get_v1_json_dump()).expect("schemas");

        let named_selector_string =
            generate_selectors(schemas.clone(), Some("account_manager.cmx".to_string()))
                .expect("Generating selectors with matching name should succeed.");

        let expected_named_selector_string = "\
            realm1/realm2/session5/account_manager.cmx:root/accounts:active\n\
            realm1/realm2/session5/account_manager.cmx:root/accounts:total\n\
            realm1/realm2/session5/account_manager.cmx:root/auth_providers:types\n\
            realm1/realm2/session5/account_manager.cmx:root/listeners:active\n\
            realm1/realm2/session5/account_manager.cmx:root/listeners:events\n\
            realm1/realm2/session5/account_manager.cmx:root/listeners:total_opened";

        assert_eq!(named_selector_string, expected_named_selector_string);

        assert_eq!(
            generate_selectors(schemas.clone(), Some("bloop.cmx".to_string()))
                .expect("Generating selectors with unmatching name should succeed"),
            ""
        );

        assert_eq!(
            generate_selectors(schemas, None)
                .expect("Generating selectors with no name should succeed"),
            expected_named_selector_string
        );
    }

    fn setup_and_run_selector_filtering(
        selector_string: &str,
        source_hierarchy: serde_json::Value,
        golden_json: serde_json::Value,
        requested_component: Option<String>,
    ) {
        let mut selector_path =
            tempfile::NamedTempFile::new().expect("Creating tmp selector file should succeed.");

        selector_path
            .write_all(selector_string.as_bytes())
            .expect("writing selectors to file should be fine...");

        let schemas: Vec<InspectData> =
            serde_json::from_value(source_hierarchy).expect("load schemas");
        let filtered_data_string = filter_data_to_lines(
            &selector_path.path().to_string_lossy(),
            &schemas,
            &requested_component,
        )
        .expect("filtering hierarchy should have succeeded.")
        .into_iter()
        .filter(|line| !line.removed)
        .fold(String::new(), |mut acc, line| {
            acc.push_str(&line.value);
            acc
        });
        let filtered_json_value: serde_json::Value = serde_json::from_str(&filtered_data_string)
            .expect(&format!(
                "Resultant json dump should be parsable json: {}",
                filtered_data_string
            ));

        assert_eq!(filtered_json_value, golden_json);
    }

    #[test]
    fn trailing_comma_diff_test() {
        let trailing_comma_hierarchy = serde_json::json!(
            [
                {
                    "data_source": "Inspect",
                    "metadata": {
                        "errors": null,
                        "filename": "fuchsia.inspect.Tree",
                        "component_url": "fuchsia-pkg://fuchsia.com/blooper#meta/blooper.cmx",
                        "timestamp": 0
                    },
                    "moniker": "blooper.cmx",
                    "payload": {
                        "root": {
                            "a": {
                                "b": 0,
                                "c": 1
                            }
                        }
                    },
                    "version": 1
                }
            ]
        );

        let selector = "blooper.cmx:root/a:b";
        let mut selector_path =
            tempfile::NamedTempFile::new().expect("Creating tmp selector file should succeed.");

        selector_path
            .write_all(selector.as_bytes())
            .expect("writing selectors to file should be fine...");
        let mut schemas: Vec<InspectData> =
            serde_json::from_value(trailing_comma_hierarchy).expect("ok");
        for schema in schemas.iter_mut() {
            if let Some(hierarchy) = &mut schema.payload {
                hierarchy.sort();
            }
        }
        let filtered_data_string = filter_data_to_lines(
            &selector_path.path().to_string_lossy(),
            &schemas,
            &Some("blooper.cmx".to_string()),
        )
        .expect("filtering hierarchy should succeed.");

        let removed_lines = filtered_data_string.iter().fold(HashSet::new(), |mut acc, line| {
            if line.removed {
                eprintln!("line removed bloop:{}", line.value.clone());
                acc.insert(line.value.clone());
            }
            acc
        });

        assert!(removed_lines.len() == 1);
        assert!(removed_lines.contains(&r#"          "c": 1"#.to_string()));
    }

    #[test]
    fn v1_filter_data_to_lines_test() {
        let full_tree_selector = "*/realm2/session5/account_manager.cmx:root/accounts:active
realm1/realm*/sessio*/account_manager.cmx:root/accounts:total
realm1/realm2/session5/account_manager.cmx:root/auth_providers:types
realm1/realm2/session5/account_manager.cmx:root/listeners:active
realm1/realm2/session5/account_*:root/listeners:events
realm1/realm2/session5/account_manager.cmx:root/listeners:total_opened";

        setup_and_run_selector_filtering(
            full_tree_selector,
            get_v1_json_dump(),
            get_v1_json_dump(),
            None,
        );

        setup_and_run_selector_filtering(
            full_tree_selector,
            get_v1_json_dump(),
            get_v1_json_dump(),
            Some("account_manager.cmx".to_string()),
        );

        let single_value_selector =
            "realm1/realm2/session5/account_manager.cmx:root/accounts:active";

        setup_and_run_selector_filtering(
            single_value_selector,
            get_v1_json_dump(),
            get_v1_single_value_json(),
            None,
        );

        setup_and_run_selector_filtering(
            single_value_selector,
            get_v1_json_dump(),
            get_v1_single_value_json(),
            Some("account_manager.cmx".to_string()),
        );

        setup_and_run_selector_filtering(
            single_value_selector,
            get_v1_json_dump(),
            get_empty_value_json(),
            Some("bloop.cmx".to_string()),
        );
    }

    fn get_v1_json_dump() -> serde_json::Value {
        serde_json::json!(
            [
                {
                    "data_source":"Inspect",
                    "metadata":{
                        "errors":null,
                        "filename":"fuchsia.inspect.Tree",
                        "component_url": "fuchsia-pkg://fuchsia.com/account#meta/account_manager.cmx",
                        "timestamp":0
                    },
                    "moniker":"realm1/realm2/session5/account_manager.cmx",
                    "payload":{
                        "root": {
                            "accounts": {
                                "active": 0,
                                "total": 0
                            },
                            "auth_providers": {
                                "types": "google"
                            },
                            "listeners": {
                                "active": 1,
                                "events": 0,
                                "total_opened": 1
                            }
                        }
                    },
                    "version":1
                }
            ]
        )
    }

    fn get_v1_single_value_json() -> serde_json::Value {
        serde_json::json!(
            [
                {
                    "data_source":"Inspect",
                    "metadata":{
                        "errors":null,
                        "filename":"fuchsia.inspect.Tree",
                        "component_url": "fuchsia-pkg://fuchsia.com/account#meta/account_manager.cmx",
                        "timestamp":0
                    },
                    "moniker":"realm1/realm2/session5/account_manager.cmx",
                    "payload":{
                        "root": {
                            "accounts": {
                                "active": 0
                            }
                        }
                    },
                    "version":1
                }
            ]
        )
    }

    fn get_empty_value_json() -> serde_json::Value {
        serde_json::json!([])
    }
}
