// 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::trace::propagation::context::PropagationContext;
use base64::decode;

/// Decode context value packed in `sw8` header.
pub fn decode_propagation(header_value: &str) -> crate::Result<PropagationContext> {
    let pieces: Vec<&str> = header_value.split('-').collect();

    if pieces.len() != 8 {
        return Err(crate::Error::DecodePropagation(
            "failed to parse propagation context: it must have 8 properties.",
        ));
    }

    let do_sample = try_parse_sample_status(pieces[0])?;
    let parent_trace_id = b64_encoded_into_string(pieces[1])?;
    let parent_trace_segment_id = b64_encoded_into_string(pieces[2])?;
    let parent_span_id: i32 = try_parse_parent_span_id(pieces[3])?;
    let parent_service = b64_encoded_into_string(pieces[4])?;
    let parent_service_instance = b64_encoded_into_string(pieces[5])?;
    let destination_endpoint = b64_encoded_into_string(pieces[6])?;
    let destination_address = b64_encoded_into_string(pieces[7])?;

    let context = PropagationContext::new(
        do_sample,
        parent_trace_id,
        parent_trace_segment_id,
        parent_span_id,
        parent_service,
        parent_service_instance,
        destination_endpoint,
        destination_address,
    );

    Ok(context)
}

fn try_parse_parent_span_id(id: &str) -> crate::Result<i32> {
    if let Ok(result) = id.parse::<i32>() {
        Ok(result)
    } else {
        Err(crate::Error::DecodePropagation(
            "failed to parse span id from parent.",
        ))
    }
}

fn try_parse_sample_status(status: &str) -> crate::Result<bool> {
    if status == "0" {
        Ok(false)
    } else if status == "1" {
        Ok(true)
    } else {
        Err(crate::Error::DecodePropagation(
            "failed to parse sample status.",
        ))
    }
}

fn b64_encoded_into_string(enc: &str) -> crate::Result<String> {
    if let Ok(result) = decode(enc) {
        if let Ok(decoded_str) = String::from_utf8(result) {
            return Ok(decoded_str);
        }
    }

    Err(crate::Error::DecodePropagation("failed to decode value."))
}
