#!/usr/local/bin/python

import os, sys
import ping
import Tkinter, _tkinter

class XPing:
  def __init__(self, master, hostname):
    self.hostname = hostname
    self.ping = ping.Ping(hostname)
    self.widgets(master)
    self.num_missing = 0
    _tkinter.createfilehandler(self.ping, _tkinter.READABLE, self.packet)
    self._removed = 0

  def __del__(self):
    if not self._removed:
      _tkinter.deletefilehandler(self.ping)
      self._removed = 1

  def quit(self, *args):
    self.button.quit()
  def mainloop(self):
    self.button.mainloop()

  def widgets(self, master):
    from Tkinter import Label, E, W
    frame = Tkinter.Frame(master)
    frame.master.title('Xping')
    frame.master.iconname(self.hostname)
    self.make_vars(frame)
    frame.pack(fill=Tkinter.BOTH, expand=Tkinter.YES)

    self.button = Tkinter.Button(frame, text=self.hostname,
      command=self.quit, background='green')
    self.button.grid(columnspan=2, sticky=W+E)
    status = Label(frame, textvariable=self.status,
               relief=Tkinter.GROOVE)
    status.grid(row=5, columnspan=2, sticky=W+E)

    # packets
    Label(frame, text="Packets", anchor=W).grid(row=1, column=0, sticky=W)
    Label(frame, textvariable=self.packets,
                 anchor=W).grid(row=1, column=1, sticky=E)
    # time
    Label(frame, text="Time", anchor=W).grid(row=2, column=0, sticky=W)
    Label(frame, textvariable=self.time,
                 anchor=W).grid(row=2, column=1, sticky=E)
    # arrt
    Label(frame, text='Ave RRT', anchor=W).grid(row=3, column=0, sticky=W)
    Label(frame, textvariable=self.arrt,
                 anchor=W).grid(row=3, column=1, sticky=E)
    # missing
    Label(frame, text='Missing', anchor=W).grid(row=4, column=0, sticky=W)
    Label(frame, textvariable=self.missing,
                 anchor=W).grid(row=4, column=1, sticky=E)

    frame.master.bind('<Control-c>', self.quit)
    frame.master.bind('<Control-r>', self.reset)

  def make_vars(self, master):
    self.packets = Tkinter.IntVar(master)
    self.time = Tkinter.IntVar(master)
    self.arrt = Tkinter.IntVar(master)
    self.missing = Tkinter.StringVar(master)
    self.status = Tkinter.StringVar(master)
    self.reset()

  def reset(self, *args):
    self.ping.clear()
    self.packets.set(0)
    self.time.set(0)
    self.arrt.set(0)
    self.missing.set('0%')
    self.status.set('waiting')
    self.num_missing = 0

  def packet(self, file, mask):
    try:
      num, time = self.ping.next()
      self.packets.set(num)
      self.time.set(time)
      self.arrt.set(self.ping.ave())
    except ping.Unreachable:
      self.unreachable()
    except ping.MissingPacket:
      self.missing_packet()
    else:
      self.normal()

  def normal(self):
    if self.num_missing:
      self.num_missing = 0
    self.button.configure(background='green')
    self.status.set('receiving')
  def unreachable(self):
    self.button.configure(background='red')
    self.status.set('unreachable')
  def missing_packet(self):
    if self.num_missing > 5:
      self.button.configure(background='red')
      self.status.set('no response')
    else:
      self.num_missing = self.num_missing + 1
      self.button.configure(background='yellow')
    self.missing.set("%d %%" % self.ping.droprate())

if __name__ == '__main__':

  def NoArgument(master):
    frame = Tkinter.Frame(master, relief=Tkinter.RAISED, border=2)
    Tkinter.Label(frame, text='Argument', background='red').pack(
      fill=Tkinter.X, expand=Tkinter.YES)
    Tkinter.Label(frame, text='required', background='red').pack(
      fill=Tkinter.X, expand=Tkinter.YES)
    frame.pack(fill=Tkinter.X)
    Tkinter.Button(master, text='OK', command=frame.quit).pack(
      fill=Tkinter.X)
    frame.mainloop()
    raise SystemExit, 1

  try:
    if len(sys.argv) > 1:
      XPing(None, sys.argv[1]).mainloop()
    else:
      NoArgument(None)
  except KeyboardInterrupt:
    pass

