// 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 std::hash::Hash;
use std::time::SystemTime;

use rand::RngCore;

pub struct IDGenerator {}

impl IDGenerator {
    /// ID generated by 3 parts
    /// 1. Registered service instance id
    /// 2. thread local level random u64
    /// 3. Timestamp in ms
    pub fn new_id(instance_id: i32) -> ID {
        ID::new(
            instance_id as i64,
            rand::thread_rng().next_u64() as i64,
            SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).ok().unwrap().as_millis() as i64,
        )
    }
}

/// ID is used for trace id and segment id.
/// It is combined by 3 i64 numbers, and could be formatted as `part1.part2.part3` string.
#[derive(Clone, Hash)]
pub struct ID {
    part1: i64,
    part2: i64,
    part3: i64,
}

impl ID {
    pub fn new(part1: i64, part2: i64, part3: i64) -> Self {
        ID {
            part1,
            part2,
            part3,
        }
    }

    /// Convert the literal string text back to ID object.
    /// Return Option::None if the text is not combined by 3 dot split i64 parts
    pub fn from(id_text: String) -> Result<Self, String> {
        let strings: Vec<&str> = id_text.split(".").collect();
        if strings.len() == 3 {
            let part1 = strings[0].parse::<i64>();
            if part1.is_err() { return Err("part 1 is not a i64".to_string()); }
            let part2 = strings[1].parse::<i64>();
            if part2.is_err() { return Err("part 2 is not a i64".to_string()); }
            let part3 = strings[2].parse::<i64>();
            if part3.is_err() { return Err("part 3 is not a i64".to_string()); }
            Ok(ID::new(part1.unwrap(), part2.unwrap(), part3.unwrap()))
        } else {
            Err("The ID is not combined by 3 parts.".to_string())
        }
    }
}

impl PartialEq for ID {
    fn eq(&self, other: &Self) -> bool {
        self.part1 == other.part1 && self.part2 == other.part2 && self.part3 == other.part3
    }
}

impl ToString for ID {
    fn to_string(&self) -> String {
        format!("{}.{}.{}", self.part1, self.part2, self.part3)
    }
}


#[cfg(test)]
mod id_tests {
    use crate::skywalking::core::ID;
    use crate::skywalking::core::id::IDGenerator;

    #[test]
    fn test_id_generator() {
        let id = IDGenerator::new_id(1);
        assert_eq!(id.part1, 1);
    }

    #[test]
    fn test_id_new() {
        let id1 = ID::new(1, 2, 3);
        let id2 = ID::new(1, 2, 3);
        let id3 = ID::new(1, 2, 4);

        assert_eq!(id1.eq(&id2), true);
        assert_eq!(id1.ne(&id3), true);
        assert_eq!(id1.to_string(), "1.2.3");

        let id4 = ID::from(String::from("1.2.3")).unwrap();
        assert_eq!(id4.eq(&id1), true);

        let id5_none = ID::from(String::from("1.2"));
        assert_ne!(id5_none.err().unwrap().len(), 0);

        let id6_illegal = ID::from(String::from("1.2.a"));
        assert_ne!(id6_illegal.err().unwrap().len(), 0);
    }
}