import statistics

class MtrHop:
    def __init__(self, idx):
        self.idx = idx
        self.host = '???'
        self.timings = []
        self.received_count = 0

class MtrParser:
    def __init__(self):
        self.hops = {}

    def update(self, line):
        parts = line.strip().split()
        if len(parts) < 3:
            return
        
        type, idx_str, value = parts[0], parts[1], parts[2]

        if type not in ('h', 'd', 'p'):
            return
        
        try:
            idx = int(idx_str)
        except ValueError:
            return

        if idx not in self.hops:
            self.hops[idx] = MtrHop(idx)
        
        hop = self.hops[idx]
        if type == 'h':
            hop.host = value
        elif type == 'p':
            hop.received_count += 1
            try:
                hop.timings.append(float(value) / 1000.0)
            except ValueError:
                pass

    def render_table(self):
        if not self.hops:
            return ""

        sorted_hops = sorted(self.hops.values(), key=lambda h: h.idx)
        
        if len(sorted_hops) >= 2 and sorted_hops[-1].host == sorted_hops[-2].host:
            sorted_hops.pop(-1)

        col_widths = {'host': 43, 'loss': 7, 'snt': 5, 'last': 7, 'avg': 7, 'best': 7, 'wrst': 7, 'stdev': 7}
        header = (
            f"{'Host':<{col_widths['host']}}"
            f"{'Loss%':>{col_widths['loss']}}"
            f"{'Snt':>{col_widths['snt']}}"
            f"{'Last':>{col_widths['last']}}"
            f"{'Avg':>{col_widths['avg']}}"
            f"{'Best':>{col_widths['best']}}"
            f"{'Wrst':>{col_widths['wrst']}}"
            f"{'StDev':>{col_widths['stdev']}}\n"
        )
        output = header
        
        for hop in sorted_hops:
            received = hop.received_count
            loss_percent = 0.0

            if received > 0:
                last, avg, best, worst, stdev = (
                    hop.timings[-1],
                    statistics.mean(hop.timings),
                    min(hop.timings),
                    max(hop.timings),
                    statistics.stdev(hop.timings) if received > 1 else 0.0,
                )
            else:
                last, avg, best, worst, stdev = 0.0, 0.0, 0.0, 0.0, 0.0

            host_str = f" {hop.idx:d}.|-- {hop.host}"
            loss_str = f"{loss_percent:.1f}%"
            
            row = (
                f"{host_str:<{col_widths['host']}}"
                f"{loss_str:>{col_widths['loss']}}"
                f"{hop.received_count:>{col_widths['snt']}}"
                f"{last:>{col_widths['last']}.1f}"
                f"{avg:>{col_widths['avg']}.1f}"
                f"{best:>{col_widths['best']}.1f}"
                f"{worst:>{col_widths['wrst']}.1f}"
                f"{stdev:>{col_widths['stdev']}.1f}\n"
            )
            output += row
            
        return output