#!/usr/bin/python

### This program is free software; you can redistribute it and/or modify
### it under the terms of the GNU Library General Public License as published by
### the Free Software Foundation; version 2 only
###
### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
### GNU Library General Public License for more details.
###
### You should have received a copy of the GNU Library General Public License
### along with this program; if not, write to the Free Software
### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
### Copyright 2004, 2005, 2006 Dag Wieers <dag@wieers.com>

import sys, signal, re, time
from pythonwifi import iwlibs

VERSION = '0.1'

ansi = {
	'default': '\033[0;0m',

	'black': '\033[0;30m',
	'darkred': '\033[0;31m',
	'darkgreen': '\033[0;32m',
	'darkyellow': '\033[0;33m',
	'darkblue': '\033[0;34m',
	'darkmagenta': '\033[0;35m',
	'darkcyan': '\033[0;36m',
	'silver': '\033[0;37m',

	'gray': '\033[1;30m',
	'red': '\033[1;31m',
	'green': '\033[1;32m',
	'yellow': '\033[1;33m',
	'blue': '\033[1;34m',
	'magenta': '\033[1;35m',
	'cyan': '\033[1;36m',
	'white': '\033[1;37m',

	'blackbg': '\033[40m',
	'redbg': '\033[41m',
	'greenbg': '\033[42m',
	'yellowbg': '\033[43m',
	'bluebg': '\033[44m',
	'magentabg': '\033[45m', 
	'cyanbg': '\033[46m',
	'whitebg': '\033[47m',

	'reset': '\033[0;0m',
	'bold': '\033[1m',
	'reverse': '\033[2m',
	'underline': '\033[4m',

	'home': '\033[H',

	'up': '\033[1A',
	'down': '\033[1B',
	'right': '\033[1C',
	'left': '\033[1D',

	'clear': '\033[2J',
	'cleareol': '\033[K',
	'clearline': '\033[2K',
#	'save': '\033[s',
#	'restore': '\033[u',
	'save': '\0337',
	'restore': '\0338',
}

def sortfunc(a, b):
	if a['active'] and b['active']:
		return cmp(b['quality'], a['quality'])
	elif not a['active'] and b['active']:
		return 1
	elif a['active'] and not b['active']:
		return -1
	else:
		return cmp(b['timestamp'], a['timestamp'])

print ansi['clear']

apsidx = {}
aps = []
try:
	while True:
		print ansi['home'] + ansi['blue'] + " %-14s  %4s  %-17s  %-5s  %-8s  %8s  %3s  %4s  %4s  %3s  %8s  %3s" % ('Essid', 'Chan', 'HW address', 'Iface', 'Max rate', 'Last bcn', 'Qua', 'Sgnl', 'Nois', 'S/N', 'Cur rate', 'Mis')

		for iface in iwlibs.getNICnames():
			ifobj = iwlibs.Wireless(iface)
			scanresults = ifobj.scan()
			for result in scanresults:
				idx = [x for x, y in enumerate(aps) if y['bssid'] == result.bssid]
				beacon = int(re.match('.*Last beacon: ([0-9]+)ms ago', result.custom[1]).group(1))
				obj = {
					'essid': result.essid, 
					'bssid': result.bssid, 
					'quality': result.quality.quality, 
					'signal': result.quality.getSignallevel(), 
					'noise': result.quality.getNoiselevel(), 
					'lastbeacon': beacon, 
					'timestamp': time.time() - beacon/1000, 
					'encode': result.encode, 
					'channel': result.frequency.getChannel(result.frequency.getFrequency(), result.range), 
					'maxrate': result.rate[-1], 
					'active': True,
				}

				if idx:
					aps[idx[0]] = obj
				else:
					aps.append(obj)
	
		aps.sort(sortfunc)

		for idx, obj in enumerate(aps):
			bcol = ' '
			fcol = ansi['default']
			if not obj['active']:
				bcol = ansi['gray'] + '!'
				fcol = ansi['gray']
			for iface in iwlibs.getNICnames():
				ifobj = iwlibs.Wireless(iface)
				if obj['bssid'] == ifobj.getAPaddr():
					bcol = ansi['white'] + '+'
					fcol = ansi['white']
					stat, qual, discard, missed_beacon = ifobj.getStatistics()
					break

			if (map(lambda x: hex(ord(x)), obj['encode']) == ['0x0','0x0','0x0','0x8']):
				ecol = ansi['red']
				if not obj['active']: ecol = ansi['darkred']
			else:
				ecol = ansi['green']
				if not obj['active']: ecol = ansi['darkgreen']

			if obj['active']:
				beacon = (' %5d ms ' % obj['lastbeacon'])
			else:
				beacon = ('  %5d s ' % (time.time() - obj['timestamp']))

			print bcol + ecol + ('%-14s ' % obj['essid'].encode('ascii', 'replace')) + fcol + (' %(channel)4s  %(bssid)-17s ' % obj) + (' %-5s ' % iface) + (' %8s ' % obj['maxrate']) + beacon + (' %3s ' % obj['quality']),

			if obj['bssid'] == ifobj.getAPaddr():
				print '%4s  %4s  %3s  %8s  %3s' % (qual.signallevel, qual.noiselevel, qual.signallevel - qual.noiselevel, ifobj.getBitrate(), missed_beacon),
#			else:
#				print ansi['gray'] + '%4s  %4s  %3s  %8s  %3s' % (obj['signal'], obj['noise'], int(obj['signal']) - int(obj['noise']), '-', '-'),
				
			print ansi['silver']+ansi['cleareol']

			aps[idx]['active'] = False

		print ansi['blue'] + ' %s access points (%s active and %s inactive)' % (len(aps), len(scanresults), len(aps) - len(scanresults))
		time.sleep(0.04)

except KeyboardInterrupt, e:
	print

# vim:ts=4:sw=4
