// Copyright 2020 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.

// [START part_1_add_connection_count]
use {
    // [START_EXCLUDE]
    fidl_fuchsia_examples_inspect::{ReverserRequest, ReverserRequestStream},
    fuchsia_async as fasync,
    fuchsia_inspect as inspect,
    // [END_EXCLUDE]
    fuchsia_inspect::NumericProperty,
    // [START_EXCLUDE]
    futures::TryStreamExt,
    std::sync::Arc,
    // [END_EXCLUDE]
};

pub struct ReverserServerFactory {
    node: inspect::Node,
    // [START_EXCLUDE]
    request_count: Arc<inspect::UintProperty>,
    // [END_EXCLUDE]
    connection_count: inspect::UintProperty,
}

impl ReverserServerFactory {
    pub fn new(node: inspect::Node) -> Self {
        // [START_EXCLUDE]
        let request_count = Arc::new(node.create_uint("total_requests", 0));
        // [END_EXCLUDE]
        let connection_count = node.create_uint("connection_count", 0);
        Self {
            node,
            // [START_EXCLUDE]
            request_count,
            // [END_EXCLUDE]
            connection_count,
        }
    }

    pub fn spawn_new(&self, stream: ReverserRequestStream) {
        self.connection_count.add(1);
        // [END part_1_add_connection_count]
        let node = self.node.create_child(inspect::unique_name("connection"));
        let metrics = ReverserServerMetrics::new(node, self.request_count.clone());
        ReverserServer::new(metrics).spawn(stream);
    }
}

// The default implementation of ReverserServerMetrics is a no-op on the inspect properties. We use
// it for testing in this codelab. Future parts of the codelab will actually test our inspect
// writing.
#[derive(Default)]
struct ReverserServerMetrics {
    global_request_count: Arc<inspect::UintProperty>,
    request_count: inspect::UintProperty,
    response_count: inspect::UintProperty,
    _node: inspect::Node,
}

impl ReverserServerMetrics {
    fn new(node: inspect::Node, global_request_count: Arc<inspect::UintProperty>) -> Self {
        let request_count = node.create_uint("request_count", 0);
        let response_count = node.create_uint("response_count", 0);
        let metrics = Self {
            global_request_count,
            // Hold to the node until we are done with this connection.
            _node: node,
            request_count,
            response_count,
        };
        metrics
    }
}

struct ReverserServer {
    metrics: ReverserServerMetrics,
}

impl ReverserServer {
    fn new(metrics: ReverserServerMetrics) -> Self {
        Self { metrics }
    }

    pub fn spawn(self, mut stream: ReverserRequestStream) {
        fasync::Task::local(async move {
            let _ = &self;
            while let Some(request) = stream.try_next().await.expect("serve reverser") {
                self.metrics.request_count.add(1);
                self.metrics.global_request_count.add(1);

                let ReverserRequest::Reverse { input, responder } = request;
                let result = input.chars().rev().collect::<String>();
                responder.send(&result).expect("send reverse request response");

                self.metrics.response_count.add(1);
            }
        })
        .detach();
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        anyhow::Error,
        fidl_fuchsia_examples_inspect::{ReverserMarker, ReverserProxy},
        // CODELAB: Include the inspect test module.
    };

    #[fuchsia::test]
    async fn test_reverser() -> Result<(), Error> {
        let reverser = open_reverser()?;
        let result = reverser.reverse("hello").await?;
        assert_eq!(result, "olleh");
        // CODELAB: assert that the inspect data is correct.
        Ok(())
    }

    fn open_reverser() -> Result<ReverserProxy, Error> {
        let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<ReverserMarker>()?;
        let reverser = ReverserServer::new(ReverserServerMetrics::default());
        reverser.spawn(stream);
        Ok(proxy)
    }
}
