// 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 serde::Deserialize;
use serde::Serialize;
use serde_json::Map;
use serde_json::Value;

use std::collections::HashMap;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::PathBuf;

#[derive(Serialize, Deserialize)]
pub struct TableOfContentsItem {
    pub name: String,
    pub link: String,
    pub description: String,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct FidlJson {
    pub version: String,
    pub name: String,
    #[serde(default)]
    pub maybe_attributes: Vec<Value>,
    pub library_dependencies: Vec<Value>,
    pub bits_declarations: Vec<Value>,
    pub const_declarations: Vec<Value>,
    pub enum_declarations: Vec<Value>,
    pub interface_declarations: Vec<Value>,
    pub table_declarations: Vec<Value>,
    pub type_alias_declarations: Vec<Value>,
    pub struct_declarations: Vec<Value>,
    pub union_declarations: Vec<Value>,
    pub declaration_order: Vec<String>,
    pub declarations: Map<String, Value>,
}

impl FidlJson {
    pub fn from_path(path: &PathBuf) -> Result<FidlJson, io::Error> {
        let mut fidl_file = match File::open(path) {
            Err(why) => {
                eprintln!(
                    "Couldn't open file {path}: {reason}",
                    path = path.display(),
                    reason = why,
                );
                return Err(why);
            }
            Ok(file) => file,
        };

        let mut s = String::new();
        fidl_file.read_to_string(&mut s)?;

        Ok(serde_json::from_str(&s)?)
    }

    pub fn sort_declarations(&mut self) {
        let cmp_name = |a: &Value, b: &Value| a["name"].as_str().cmp(&b["name"].as_str());
        let FidlJson {
            version: _,
            name: _,
            maybe_attributes: _,
            library_dependencies: _,
            bits_declarations,
            const_declarations,
            enum_declarations,
            interface_declarations,
            table_declarations,
            type_alias_declarations,
            struct_declarations,
            union_declarations,
            declaration_order: _,
            declarations: _,
        } = self;
        bits_declarations.sort_unstable_by(cmp_name);
        const_declarations.sort_unstable_by(cmp_name);
        enum_declarations.sort_unstable_by(cmp_name);
        interface_declarations.sort_unstable_by(cmp_name);
        for interface in interface_declarations.iter_mut() {
            interface["methods"].as_array_mut().unwrap().sort_unstable_by(cmp_name);
        }
        table_declarations.sort_unstable_by(cmp_name);
        type_alias_declarations.sort_unstable_by(cmp_name);
        struct_declarations.sort_unstable_by(cmp_name);
        union_declarations.sort_unstable_by(cmp_name);
    }
}

pub struct FidlJsonPackageData {
    pub declarations: Vec<String>,
    pub fidl_json_map: HashMap<String, FidlJson>,
}

impl FidlJsonPackageData {
    pub fn new() -> Self {
        FidlJsonPackageData { declarations: Vec::new(), fidl_json_map: HashMap::new() }
    }

    pub fn insert(&mut self, mut fidl_json: FidlJson) {
        self.declarations.append(&mut fidl_json.declaration_order);
        let package_name = fidl_json.name.clone();
        self.fidl_json_map
            .entry(package_name)
            .and_modify(|package_fidl_json| {
                // Merge
                package_fidl_json.maybe_attributes.append(&mut fidl_json.maybe_attributes);
                package_fidl_json.bits_declarations.append(&mut fidl_json.bits_declarations);
                package_fidl_json.const_declarations.append(&mut fidl_json.const_declarations);
                package_fidl_json.enum_declarations.append(&mut fidl_json.enum_declarations);
                package_fidl_json
                    .interface_declarations
                    .append(&mut fidl_json.interface_declarations);
                package_fidl_json.struct_declarations.append(&mut fidl_json.struct_declarations);
                package_fidl_json.table_declarations.append(&mut fidl_json.table_declarations);
                package_fidl_json
                    .type_alias_declarations
                    .append(&mut fidl_json.type_alias_declarations);
                package_fidl_json.union_declarations.append(&mut fidl_json.union_declarations);
                package_fidl_json.declaration_order.append(&mut fidl_json.declaration_order);
            })
            .or_insert(fidl_json);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use serde_json::json;

    #[test]
    fn sort_declarations_test() {
        let mut f = FidlJson {
            name: "fuchsia.test".to_string(),
            version: "0.0.1".to_string(),
            maybe_attributes: vec![json!({"name": "Doc", "value": "Fuchsia Test API"})],
            library_dependencies: Vec::new(),
            bits_declarations: serde_json::from_str("[{\"name\": \"ABit\"},{\"name\": \"LastBit\"},{\"name\": \"AnotherBit\"}]").unwrap(),
            const_declarations: serde_json::from_str("[{\"name\": \"fuchsia.test/Const\"},{\"name\": \"fuchsia.test/AConst\"}]").unwrap(),
            enum_declarations: serde_json::from_str("[{\"name\": \"fuchsia.test/Enum\"},{\"name\": \"fuchsia.test/Third\"},{\"name\": \"fuchsia.test/Second\"}]").unwrap(),
            interface_declarations: serde_json::from_str("[{\"name\": \"Protocol1\",\"methods\": [{\"name\": \"Method 2\"},{\"name\": \"Method 1\"}]},{\"name\": \"AnotherProtocol\",\"methods\": [{\"name\": \"AMethod\"},{\"name\": \"BMethod\"}]}]").unwrap(),
            table_declarations: serde_json::from_str("[{\"name\": \"4\"},{\"name\": \"2A\"},{\"name\": \"11\"},{\"name\": \"zzz\"}]").unwrap(),
            type_alias_declarations: serde_json::from_str("[{\"name\": \"fuchsia.test/type\"},{\"name\": \"fuchsia.test/alias\"}]").unwrap(),
            struct_declarations: serde_json::from_str("[{\"name\": \"fuchsia.test/SomeLongAnonymousPrefix1\"},{\"name\": \"fuchsia.test/Struct\"},{\"name\": \"fuchsia.test/SomeLongAnonymousPrefix0\"}]").unwrap(),
            union_declarations: serde_json::from_str("[{\"name\": \"union1\"},{\"name\": \"Union1\"},{\"name\": \"UnIoN1\"}]").unwrap(),
            declaration_order: Vec::new(),
            declarations: Map::new(),
        };

        f.sort_declarations();

        assert_eq!(&f.bits_declarations[0]["name"], "ABit");
        assert_eq!(&f.bits_declarations[1]["name"], "AnotherBit");
        assert_eq!(&f.bits_declarations[2]["name"], "LastBit");

        assert_eq!(&f.const_declarations[0]["name"], "fuchsia.test/AConst");
        assert_eq!(&f.const_declarations[1]["name"], "fuchsia.test/Const");

        assert_eq!(&f.enum_declarations[0]["name"], "fuchsia.test/Enum");
        assert_eq!(&f.enum_declarations[1]["name"], "fuchsia.test/Second");
        assert_eq!(&f.enum_declarations[2]["name"], "fuchsia.test/Third");

        assert_eq!(&f.table_declarations[0]["name"], "11");
        assert_eq!(&f.table_declarations[1]["name"], "2A");
        assert_eq!(&f.table_declarations[2]["name"], "4");
        assert_eq!(&f.table_declarations[3]["name"], "zzz");

        assert_eq!(&f.type_alias_declarations[0]["name"], "fuchsia.test/alias");
        assert_eq!(&f.type_alias_declarations[1]["name"], "fuchsia.test/type");

        assert_eq!(&f.struct_declarations[0]["name"], "fuchsia.test/SomeLongAnonymousPrefix0");
        assert_eq!(&f.struct_declarations[1]["name"], "fuchsia.test/SomeLongAnonymousPrefix1");
        assert_eq!(&f.struct_declarations[2]["name"], "fuchsia.test/Struct");

        assert_eq!(&f.union_declarations[0]["name"], "UnIoN1");
        assert_eq!(&f.union_declarations[1]["name"], "Union1");
        assert_eq!(&f.union_declarations[2]["name"], "union1");
    }
}
