// Copyright 2022 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 crate::{BUILD_INFO_PROTOCOL, ELF_TEST_RUNNER_SHARD};

#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Warning {
    /// Users must declare any capabilities that are provided by the component
    DeclareExpose,

    /// Users might want to use gtest/gunit/rust/gotest but we don't yet support them
    ElfTestRunnerUsed,

    /// CMX had includes that we naively converted to .cml
    IncludesRenamed,

    /// Component retrieved build info through directory API and must switch to protocol.
    BuildInfoImpl,

    /// Component asks for hub feature
    UsesHub,

    /// Child needs an additional GN target added to package, possibly capabilities routed to it
    ChildNeedsGnTargetAndRouting { child: String, gn_target: String },

    /// Component must be added to the storage index
    StorageIndex,

    /// Test will require a mock for config-data
    ConfigDataInTest,

    /// Component uses device directories but we can't translate them perfectly
    DeviceDirectoryBestEffort,

    /// Test asks for a protocol that's unavailable to hermetic & system tests
    TestWithUnavailableProtocol(String),
}

const EXPOSE_WARNING: &str = r#"
// WARNING: Components must declare capabilities they provide to parents.
//          Either delete or uncomment and populate these lines:
//
// capabilities: [
//     "fuchsia.example.Protocol",
// ],
// expose: [
//     {
//          protocol: [ "fuchsia.example.Protocol" ],
//          from: "self",
//     },
// ],"#;

const ELF_TEST_RUNNER_WARNING: &str = r#"
// NOTE: You may want to choose a test runner that understands your language's tests. See
// https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#inventory_of_test_runners
// for details.
"#;

const INCLUDE_RENAME_WARNING: &str = r#"
// WARNING: These includes have been mechanically renamed from .cmx to .cml, it's possible
// that some of them do not yet have CML equivalents. Check with authors of the v1 shards
// if you get build errors using this manifest."#;

const BUILD_INFO_WARNING: &str = r#"
// WARNING: Build info is delivered differently in v1 & v2. See
// https://fuchsia.dev/fuchsia-src/development/components/v2/migration/features#build-info."#;

const HUB_WARNING: &str = r#"
// WARNING: Event streams replace the hub for testing in v2. For more information:
// https://fuchsia.dev/fuchsia-src/development/components/v2/migration/features#events"#;

const STORAGE_INDEX_WARNING: &str = r#"
// NOTE: Using persistent storage requires updating the storage index. For more details:
// https://fuchsia.dev/fuchsia-src/development/components/v2/migration/features#update_component_storage_index"#;

const CONFIG_DATA_TEST_WARNING: &str = r#"
// NOTE: config-data in tests requires specifying the package:
// https://fuchsia.dev/fuchsia-src/development/components/v2/migration/features?hl=en#configuration_data_in_tests
"#;

const DEVICE_DIRECTORY_WARNING: &str = r#"
// WARNING: Device directories are converted as best-effort and may need either different rights or
// a different directory name to function in v2."#;

const UNAVAILABLE_TEST_PROTOCOL_WARNING: &str = r#"
// WARNING: This protocol is not normally available to tests, you may need to add it to the
// system test realm or add a mock/fake implementation as a child.
"#;

impl Warning {
    pub fn apply(&self, lines: &mut Vec<String>) {
        match self {
            Warning::DeclareExpose => {
                let use_or_end_idx =
                    lines.iter().position(|l| l == "    use: [").unwrap_or_else(|| {
                        lines.iter().position(|l| l == "}").expect(
                            "generated manifests all have a closing brace on their own line",
                        )
                    });
                lines.insert(use_or_end_idx, EXPOSE_WARNING.to_string());
            }
            Warning::ElfTestRunnerUsed => {
                let runner_shard_idx = lines
                    .iter()
                    .position(|l| l.contains(ELF_TEST_RUNNER_SHARD))
                    .expect("files with the elf test runner warning must include the shard");
                lines.insert(runner_shard_idx, ELF_TEST_RUNNER_WARNING.to_string());
            }
            Warning::IncludesRenamed => {
                let includes_idx = lines
                    .iter()
                    .position(|l| l.starts_with("    include: ["))
                    .expect("files with include conversion warnings must have an include block");
                lines.insert(includes_idx, INCLUDE_RENAME_WARNING.to_string());
            }
            Warning::BuildInfoImpl => {
                let build_info_proto_idx = lines
                    .iter()
                    .position(|l| l.contains(BUILD_INFO_PROTOCOL))
                    .expect("files with build info warning list the build info protocol");
                lines.insert(build_info_proto_idx, BUILD_INFO_WARNING.to_string());
            }
            Warning::UsesHub => {
                let opening_brace_idx = lines
                    .iter()
                    .position(|l| l == "{")
                    .expect("all files have an opening brace on its own line");
                lines.insert(opening_brace_idx, HUB_WARNING.to_string());
            }
            Warning::StorageIndex => {
                let storage_idx = lines
                    .iter()
                    .position(|l| l.contains("storage: \"data\","))
                    .expect("files with storage index warnings have a persistent data directory");
                lines.insert(storage_idx, STORAGE_INDEX_WARNING.to_string());
            }
            Warning::ChildNeedsGnTargetAndRouting { child, gn_target } => {
                let child_name_idx = lines
                    .iter()
                    .position(|l| l.contains("name: ") && l.contains(&*child))
                    .expect("child warnings are only emitted for children we have");
                lines.insert(
                    child_name_idx,
                    format!(
                        r#"
// WARNING: This child must be packaged with your component. The package should depend on:
//     {}
// Note that you may need to route additional capabilities to this child."#,
                        gn_target
                    ),
                );
            }
            Warning::ConfigDataInTest => {
                let config_data_idx = lines
                    .iter()
                    .position(|l| l.contains("config-data"))
                    .expect("config-data warnings are only emitted for cml's with the use");
                lines.insert(config_data_idx, CONFIG_DATA_TEST_WARNING.to_string());
            }
            Warning::DeviceDirectoryBestEffort => {
                let dev_idx = lines
                    .iter()
                    .position(|l| l.contains("directory: \"dev-"))
                    .expect("device dir warnings are only emitted for cml's with devices");
                lines.insert(dev_idx, DEVICE_DIRECTORY_WARNING.to_string());
            }
            Warning::TestWithUnavailableProtocol(protocol) => {
                let proto_idx = lines
                    .iter()
                    .position(|l| l.contains(&*protocol))
                    .expect("uses must have protocol listed if we're warning about it");
                lines.insert(proto_idx, UNAVAILABLE_TEST_PROTOCOL_WARNING.to_string());
            }
        }
    }
}
