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

use crate::{
    common::system_time::{fetch_time, TimePeriod},
    skywalking_proto::v3::{
        log_data_body::Content, JsonLog, KeyStringValuePair, LogData, LogDataBody, LogTags,
        TextLog, TraceContext, YamlLog,
    },
    trace::{span::Span, trace_context::TracingContext},
};
use std::time::{SystemTime, UNIX_EPOCH};

pub enum RecordType {
    Text,
    Json,
    Yaml,
}

impl Default for RecordType {
    fn default() -> Self {
        Self::Text
    }
}

#[derive(Default)]
pub struct LogRecord {
    time: Option<SystemTime>,
    is_ignore_time: bool,
    endpoint: String,
    tags: Vec<(String, String)>,
    trace_id: Option<String>,
    trace_segment_id: Option<String>,
    span_id: Option<i32>,
    record_type: RecordType,
    content: String,
}

impl LogRecord {
    #[inline]
    pub fn new() -> Self {
        Default::default()
    }

    #[inline]
    pub fn custome_time(mut self, time: SystemTime) -> Self {
        self.time = Some(time);
        self
    }

    #[inline]
    pub fn ignore_time(mut self) -> Self {
        self.is_ignore_time = true;
        self
    }

    #[inline]
    pub fn endpoint(mut self, endpoint: impl Into<String>) -> Self {
        self.endpoint = endpoint.into();
        self
    }

    pub fn add_tag(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
        self.tags.push((key.into(), value.into()));
        self
    }

    pub fn add_tags<K, V, I>(mut self, tags: I) -> Self
    where
        K: Into<String>,
        V: Into<String>,
        I: IntoIterator<Item = (K, V)>,
    {
        self.tags
            .extend(tags.into_iter().map(|(k, v)| (k.into(), v.into())));
        self
    }

    pub fn with_tracing_context(mut self, tracing_context: &TracingContext) -> Self {
        self.trace_id = Some(tracing_context.trace_id().to_owned());
        self.trace_segment_id = Some(tracing_context.trace_segment_id().to_owned());
        self
    }

    pub fn with_span(mut self, span: &Span) -> Self {
        self.span_id = Some(span.with_span_object(|span| span.span_id));
        self
    }

    pub fn record_type(mut self, record_type: RecordType) -> Self {
        self.record_type = record_type;
        self
    }

    pub fn content(mut self, content: impl Into<String>) -> Self {
        self.content = content.into();
        self
    }

    pub(crate) fn convert_to_log_data(
        self,
        service_name: String,
        instance_name: String,
    ) -> LogData {
        let timestamp = if self.is_ignore_time {
            0
        } else {
            match self.time {
                Some(time) => time
                    .duration_since(UNIX_EPOCH)
                    .map(|dur| dur.as_millis() as i64)
                    .unwrap_or_default(),
                None => fetch_time(TimePeriod::Log),
            }
        };
        let trace_context = match (self.trace_id, self.trace_segment_id, self.span_id) {
            (Some(trace_id), Some(trace_segment_id), Some(span_id)) => Some(TraceContext {
                trace_id,
                trace_segment_id,
                span_id,
            }),
            _ => None,
        };
        let tags = if self.tags.is_empty() {
            None
        } else {
            let data = self
                .tags
                .into_iter()
                .map(|(key, value)| KeyStringValuePair { key, value })
                .collect();
            Some(LogTags { data })
        };

        LogData {
            timestamp,
            service: service_name,
            service_instance: instance_name,
            endpoint: self.endpoint,
            body: Some(LogDataBody {
                r#type: "".to_owned(),
                content: match self.record_type {
                    RecordType::Text => Some(Content::Text(TextLog { text: self.content })),
                    RecordType::Json => Some(Content::Json(JsonLog { json: self.content })),
                    RecordType::Yaml => Some(Content::Yaml(YamlLog { yaml: self.content })),
                },
            }),
            trace_context,
            tags,
            layer: Default::default(),
        }
    }
}
