from abc import ABCMeta
from typing import Optional, Tuple

from spectator.meter.age_gauge import AgeGauge
from spectator.meter.counter import Counter
from spectator.meter.dist_summary import DistributionSummary
from spectator.meter.gauge import Gauge
from spectator.meter.max_gauge import MaxGauge
from spectator.meter.meter_id import MeterId
from spectator.meter.monotonic_counter import MonotonicCounter
from spectator.meter.monotonic_counter_uint import MonotonicCounterUint
from spectator.meter.percentile_dist_summary import PercentileDistributionSummary
from spectator.meter.percentile_timer import PercentileTimer
from spectator.meter.timer import Timer

# https://netflix.github.io/atlas-docs/spectator/agent/usage/#metric-types
_METER_CLASSES = {
    'A': AgeGauge,
    'c': Counter,
    'd': DistributionSummary,
    'g': Gauge,
    'm': MaxGauge,
    'C': MonotonicCounter,
    'U': MonotonicCounterUint,
    'D': PercentileDistributionSummary,
    'T': PercentileTimer,
    't': Timer,
}


def get_meter_class(symbol: str) -> Optional[ABCMeta]:
    return _METER_CLASSES.get(symbol)


def parse_protocol_line(line: str) -> Tuple[str, MeterId, str]:
    """Parse a SpectatorD protocol line into component parts. Utility exposed for testing."""
    symbol, meter_id, value = line.split(":")
    # remove optional parts, such as gauge ttls
    symbol = symbol.split(",")[0]
    meter_id_parts = meter_id.split(",")
    name = meter_id_parts[0]

    tags = {}
    for tag in meter_id_parts[1:]:
        k, v = tag.split("=")
        tags[k] = v

    return symbol, MeterId(name, tags), value
