// Copyright 2023 Greptime Team
//
// Licensed 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 serde::{Deserialize, Serialize};
use strum::{AsRefStr, Display, EnumString};

/// Returns the protocol name represented by a wire query channel value.
pub fn channel_protocol(channel: u8) -> Option<&'static str> {
    match channel {
        1 => Some("mysql"),
        2 => Some("postgres"),
        3 => Some("httpsql"),
        4 => Some("prometheus"),
        5 => Some("otlp"),
        6 => Some("grpc"),
        7 => Some("influx"),
        8 => Some("opentsdb"),
        9 => Some("loki"),
        10 => Some("elasticsearch"),
        11 => Some("jaeger"),
        12 => Some("log"),
        13 => Some("promql"),
        14 => Some("splunk"),
        _ => None,
    }
}

/// Defines the read preference for frontend route operations,
/// determining whether to read from the region leader or follower.
#[derive(
    Debug, Clone, Copy, Default, EnumString, Display, AsRefStr, PartialEq, Serialize, Deserialize,
)]
pub enum ReadPreference {
    #[default]
    // Reads all operations from the region leader. This is the default mode.
    #[strum(serialize = "leader", to_string = "LEADER")]
    Leader,
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use crate::{ReadPreference, channel_protocol};

    #[test]
    fn test_channel_protocol() {
        let expected = [
            (1, "mysql"),
            (2, "postgres"),
            (3, "httpsql"),
            (4, "prometheus"),
            (5, "otlp"),
            (6, "grpc"),
            (7, "influx"),
            (8, "opentsdb"),
            (9, "loki"),
            (10, "elasticsearch"),
            (11, "jaeger"),
            (12, "log"),
            (13, "promql"),
            (14, "splunk"),
        ];

        for (channel, protocol) in expected {
            assert_eq!(Some(protocol), channel_protocol(channel));
        }
        assert_eq!(None, channel_protocol(0));
        assert_eq!(None, channel_protocol(15));
    }

    #[test]
    fn test_read_preference() {
        assert_eq!(ReadPreference::Leader.to_string(), "LEADER");

        let read_preference = ReadPreference::from_str("LEADER").unwrap();
        assert_eq!(read_preference, ReadPreference::Leader);

        let read_preference = ReadPreference::from_str("leader").unwrap();
        assert_eq!(read_preference, ReadPreference::Leader);

        ReadPreference::from_str("follower").unwrap_err();
    }
}
