// 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::skywalking_proto::v3::{InstanceProperties, KeyStringValuePair};
use once_cell::sync::Lazy;
use std::{collections::HashMap, process};
use systemstat::{IpAddr, Platform, System};

static IPS: Lazy<Vec<String>> = Lazy::new(|| {
    System::new()
        .networks()
        .ok()
        .map(|networks| {
            networks
                .values()
                .filter(|network| {
                    network.name != "lo"
                        && !network.name.starts_with("docker")
                        && !network.name.starts_with("br-")
                })
                .flat_map(|network| {
                    network.addrs.iter().filter_map(|addr| match addr.addr {
                        IpAddr::V4(addr) => Some(addr.to_string()),
                        _ => None,
                    })
                })
                .collect()
        })
        .unwrap_or_default()
});

static HOST_NAME: Lazy<Option<String>> = Lazy::new(|| {
    hostname::get()
        .ok()
        .and_then(|hostname| hostname.into_string().ok())
});

const OS_NAME: Option<&str> = if cfg!(target_os = "linux") {
    Some("Linux")
} else if cfg!(target_os = "windows") {
    Some("Windows")
} else if cfg!(target_os = "macos") {
    Some("Mac OS X")
} else {
    None
};

#[derive(Debug, Default)]
pub struct Properties {
    inner: HashMap<String, Vec<String>>,
}

impl Properties {
    pub const KEY_HOST_NAME: &'static str = "hostname";
    pub const KEY_IPV4: &'static str = "ipv4";
    pub const KEY_LANGUAGE: &'static str = "language";
    pub const KEY_OS_NAME: &'static str = "OS Name";
    pub const KEY_PROCESS_NO: &'static str = "Process No.";
}

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

    pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) {
        self.inner.entry(key.into()).or_default().push(value.into());
    }

    pub fn update(&mut self, key: &str, value: impl Into<String>) {
        if let Some(values) = self.inner.get_mut(key) {
            *values = vec![value.into()];
        }
    }

    pub fn remove(&mut self, key: &str) {
        self.inner.remove(key);
    }

    pub fn insert_os_info(&mut self) {
        for (key, value) in build_os_info() {
            self.insert(key, value);
        }
    }

    pub(crate) fn convert_to_instance_properties(
        self,
        service_name: String,
        instance_name: String,
    ) -> InstanceProperties {
        let mut properties = Vec::new();
        for (key, values) in self.inner {
            for value in values {
                properties.push(KeyStringValuePair {
                    key: key.clone(),
                    value,
                });
            }
        }

        InstanceProperties {
            service: service_name,
            service_instance: instance_name,
            properties,
            layer: Default::default(),
        }
    }
}

fn build_os_info() -> Vec<(String, String)> {
    let mut items = Vec::new();

    if let Some(os_name) = OS_NAME.as_ref() {
        items.push((Properties::KEY_OS_NAME.to_string(), os_name.to_string()));
    }

    if let Some(host_name) = HOST_NAME.as_ref() {
        items.push((Properties::KEY_HOST_NAME.to_string(), host_name.clone()));
    }

    for ip in IPS.iter() {
        items.push((Properties::KEY_IPV4.to_string(), ip.to_string()));
    }

    items.push((
        Properties::KEY_PROCESS_NO.to_string(),
        process::id().to_string(),
    ));

    items.push((Properties::KEY_LANGUAGE.to_string(), "rust".to_string()));

    items
}
