#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       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 General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.
#
from __future__ import with_statement
import gtk
import gobject
import os
import subprocess
import os.path
import re

TIMEOUT = 5

def default_interface():
    '''returns the interface of the default route'''
    interface = None
    stdout = subprocess.check_output(['ip', 'route', 'list', 'scope', 'global'])
    for line in stdout.split('\n'):
        route = line.split(' ')
        if (len(route) >= 5 and (route[0], route[1], route[3]) == ('default', 'via', 'dev')):
            interface = route[4]
            break
    return interface

def carrier_ok(iface):
    '''check if the interface is connected'''
    iface_dir = '/sys/class/net/%s' % iface
    with open(iface_dir + '/carrier') as f:
        line = f.next().strip()
        return line == '1'

def wpa_status():
    '''returns the output of wpa_cli status.'''
    return subprocess.check_output(['wpa_cli', 'status']).strip()

def eth_status(iface):
    '''returns the status of the given interface (for the tooltip)'''
    stdout = subprocess.check_output(['ip', 'addr', 'show', 'dev', iface])
    res = ''
    for line in stdout.split('\n'):
        m = re.search('(inet6? [^ ]*) ', line)
        if m:
            res = '\n'.join([res,m.group(1)])
    return res

def interface_type(iface):
    '''http://stackoverflow.com/questions/4475420/detect-network-connection-type-in-linux/16060638#16060638)'''
    res = 'wired'
    iface_dir = '/sys/class/net/%s' % iface
    with open(iface_dir + '/type') as f:
        line = f.next().strip()
        if line == '1':
            res = 'wired'
            if ('wireless' in os.listdir(iface_dir) or
                'phy80211' in os.listdir(iface_dir)):
                res = 'wireless'
    return res

class MainApp:
    def __init__(self):
        self.icon = gtk.StatusIcon()
        self.update_icon()
        gobject.timeout_add_seconds(TIMEOUT, self.update_icon)

    def get_network_info(self):
        interface = default_interface()
        connected = False
        if interface:
            connected = carrier_ok(interface)
        return {'interface': interface, 'connected': connected}

    def get_icon_name(self, interface, connected):
        if connected:
            return 'network-%s' % interface_type(interface)
        else:
            return 'network-error'

    def get_tooltip(self, interface, connected):
        if not connected:
            res = 'Disconnected'
        else:
            res = 'Connected on %s' % interface
            if interface_type(interface) == 'wireless':
                res = '\n'.join([res, wpa_status()])
            elif interface_type(interface) == 'wired':
                res = '\n'.join([res, eth_status(interface)])
        return res

    def update_icon(self):
        info = self.get_network_info()
        icon_name = self.get_icon_name(info['interface'], info['connected'])
        self.icon.set_from_icon_name(icon_name)
        tooltip = self.get_tooltip(info['interface'], info['connected'])
        self.icon.set_tooltip_text(tooltip)
        return True

if __name__ == '__main__':
    try:
        MainApp()
        gtk.main()
    except KeyboardInterrupt:
        pass