// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Span is an important and common concept in distributed tracing system. Learn
//! Span from Google Dapper Paper.

use crate::{
    common::{
        system_time::{fetch_time, TimePeriod},
        wait_group::WaitGroup,
    },
    proto::v3::{SpanLayer, SpanObject, SpanType},
    trace::trace_context::{SpanStack, SpanUid},
};
use std::{
    fmt::{self, Formatter},
    mem::take,
    sync::{Arc, Weak},
};

/// [HandleSpanObject] contains methods to handle [SpanObject].
pub trait HandleSpanObject {
    /// Get immutable span object reference.
    fn span_object(&self) -> &SpanObject;

    /// Mutable with inner span object.
    fn span_object_mut(&mut self) -> &mut SpanObject;

    /// Get span id.
    fn span_id(&self) -> i32 {
        self.span_object().span_id
    }

    /// Add logs to the span.
    fn add_log<K, V, I>(&mut self, message: I)
    where
        K: Into<String>,
        V: Into<String>,
        I: IntoIterator<Item = (K, V)>,
    {
        self.span_object_mut().add_log(message)
    }

    /// Add tag to the span.
    fn add_tag(&mut self, key: impl Into<String>, value: impl Into<String>) {
        self.span_object_mut().add_tag(key, value)
    }
}

/// Span is a concept that represents trace information for a single RPC.
/// The Rust SDK supports Entry Span to represent inbound to a service
/// and Exit Span to represent outbound from a service.
///
/// # Example
///
/// ```
/// use skywalking::trace::tracer::Tracer;
///
/// async fn handle_request(tracer: Tracer) {
///     let mut ctx = tracer.create_trace_context();
///
///     {
///         // Generate an Entry Span when a request is received.
///         // An Entry Span is generated only once per context.
///         // Assign a variable name to guard the span not to be dropped immediately.
///         let _span = ctx.create_entry_span("op1");
///
///         // Something...
///
///         {
///             // Generates an Exit Span when executing an RPC.
///             let _span2 = ctx.create_exit_span("op2", "remote_peer");
///
///             // Something...
///
///             // Auto close span2 when dropped.
///         }
///
///         // Auto close span when dropped.
///     }
///
///     // Auto report ctx when dropped.
/// }
/// ```
#[must_use = "assign a variable name to guard the span not be dropped immediately."]
pub struct Span {
    uid: SpanUid,
    obj: Option<SpanObject>,
    wg: WaitGroup,
    stack: Arc<SpanStack>,
}

impl fmt::Debug for Span {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_struct("Span")
            .field(
                "data",
                match self.obj {
                    Some(ref obj) => obj,
                    None => &"<none>",
                },
            )
            .finish()
    }
}

const SKYWALKING_RUST_COMPONENT_ID: i32 = 11000;

impl Span {
    pub(crate) fn new(uid: SpanUid, obj: SpanObject, wg: WaitGroup, stack: Arc<SpanStack>) -> Self {
        Self {
            uid,
            obj: Some(obj),
            wg,
            stack,
        }
    }

    #[allow(clippy::too_many_arguments)]
    pub(crate) fn new_obj(
        span_id: i32,
        parent_span_id: i32,
        operation_name: String,
        remote_peer: String,
        span_type: SpanType,
        span_layer: SpanLayer,
        skip_analysis: bool,
    ) -> SpanObject {
        SpanObject {
            span_id,
            parent_span_id,
            start_time: fetch_time(TimePeriod::Start),
            operation_name,
            peer: remote_peer,
            span_type: span_type as i32,
            span_layer: span_layer as i32,
            component_id: SKYWALKING_RUST_COMPONENT_ID,
            skip_analysis,
            ..Default::default()
        }
    }

    fn is_active_span(&self) -> bool {
        let active_spans = &*self.stack.active();
        active_spans
            .last()
            .map(|span| span.uid() == self.uid)
            .unwrap_or_default()
    }

    /// The [Span] finish at current tracing context, but the current span is
    /// still alive, until [AsyncSpan] dropped.
    ///
    /// This method must be called:
    ///
    /// 1. In original thread (tracing context).
    /// 2. Current span is active span.
    ///
    /// During alive, tags, logs and attributes of the span could be changed, in
    /// any thread.
    ///
    /// # Panics
    ///
    /// Current span could by active span.
    pub fn prepare_for_async(mut self) -> AsyncSpan {
        if !self.is_active_span() {
            panic!("current span isn't active span");
        }

        self.wg.add(1);

        AsyncSpan {
            uid: self.uid,
            wg: self.wg.clone(),
            obj: take(&mut self.obj),
            stack: Arc::downgrade(&self.stack),
        }
    }
}

impl Drop for Span {
    /// Set the end time as current time, pop from context active span stack,
    /// and push to context spans.
    fn drop(&mut self) {
        self.stack.finalize_span(self.uid, take(&mut self.obj));
    }
}

impl HandleSpanObject for Span {
    #[inline]
    fn span_object(&self) -> &SpanObject {
        self.obj.as_ref().unwrap()
    }

    #[inline]
    fn span_object_mut(&mut self) -> &mut SpanObject {
        self.obj.as_mut().unwrap()
    }
}

/// Generated by [Span::prepare_for_async], tags, logs and attributes of the
/// span could be changed, in any thread.
///
/// It could be finished when dropped.
#[must_use = "assign a variable name to guard the active span not be dropped immediately."]
pub struct AsyncSpan {
    uid: SpanUid,
    obj: Option<SpanObject>,
    wg: WaitGroup,
    stack: Weak<SpanStack>,
}

impl fmt::Debug for AsyncSpan {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_struct("AsyncSpan")
            .field(
                "data",
                match self.obj {
                    Some(ref obj) => obj,
                    None => &"<none>",
                },
            )
            .finish()
    }
}

impl Drop for AsyncSpan {
    /// Set the end time as current time.
    fn drop(&mut self) {
        self.stack
            .upgrade()
            .expect("TracingContext has dropped")
            .finalize_async_span(self.uid, take(&mut self.obj).unwrap());

        self.wg.done();
    }
}

impl HandleSpanObject for AsyncSpan {
    #[inline]
    fn span_object(&self) -> &SpanObject {
        self.obj.as_ref().unwrap()
    }

    #[inline]
    fn span_object_mut(&mut self) -> &mut SpanObject {
        self.obj.as_mut().unwrap()
    }
}

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

    trait AssertSend: Send + 'static {}

    impl AssertSend for Span {}

    impl AssertSend for AsyncSpan {}
}
