from icmplib import ping, exceptions
import argparse
import signal
import sys
import time

def main():
    parser = argparse.ArgumentParser(
        description="Эмуляция команды ping",
        add_help=True
    )
    
    parser.add_argument('destination', help='Адрес узла для проверки')
    parser.add_argument('-t', action='store_true', help='Непрерывный пинг (до Ctrl+C)')
    parser.add_argument('-n', type=int, help='Число запросов (по умолчанию: 4)')
    parser.add_argument('-w', type=int, help='Таймаут ответа (мс)')
    parser.add_argument('-S', type=str, help='Адрес источника')
    args = parser.parse_args()

    pings = args.n or (None if args.t else 4)
    ping_kwargs = {
        'address': args.destination,
        'interval': 1,
        'timeout': (args.w / 1000) if args.w else 0,
        'source': args.S,
        'privileged': True
    }

    print(f"\nОбмен пакетами с {args.destination}:")
    
    seq = 1
    total_sent = 0
    total_received = 0
    times = []

    def print_stats():
        print(f"\nСтатистика ping:")
        lost = total_sent - total_received
        loss_percent = (lost / total_sent) * 100 if total_sent > 0 else 0
        print(f"    Отправлено = {total_sent}, Получено = {total_received}, Потеряно = {lost} ({loss_percent:.1f}% потерь)")
        if times:
            print(f"    Время (мс): мин. = {min(times):.0f}, макс. = {max(times):.0f}, сред. = {sum(times)/len(times):.0f}")

    def signal_handler(signum, frame):
        print_stats()
        sys.exit(0)

    # Ctrl+C
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGBREAK, signal_handler)

    try:
        while True:
            for i in range(pings):
                result = ping(**ping_kwargs, id=seq)
                if i: 
                    time.sleep(ping_kwargs['interval'])
                total_sent += 1
                if result.packets_received:
                    total_received += 1
                    times.append(result.avg_rtt)
                    print(f"Ответ от {result.address}: время={result.avg_rtt:.0f}мс")
                else:
                    print("Превышен таймаут ожидания.")
            
            if not args.t:
                break
        
        print_stats()
        sys.exit(0)

    except KeyboardInterrupt:
        signal_handler(None, None)
    except exceptions.NameLookupError:
        print(f"Ошибка: Не удалось найти имя узла \"{args.destination}\"")


if __name__ == '__main__':
    main()