#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
 Copyright (C) 2004 jan gerber <j@reboot.fm>

 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
'''

from time import *
from os import system
from urllib2 import urlopen
from pdi.icalendar import VCalendar,ICalendar
import pdi.parser
from textwrap import wrap,fill
import pygtk; pygtk.require("2.0")
import gtk
import pango
import re
import os,thread,socket

# installed by hand right now. might put it in one package. python-dateutil
from dateutil.parser import *
import time
import datetime

ics_url="http://www.reboot.fm/vcal/current.ics"
this_studio=''

# j ping version
#ping_cmd="ping -W 1 -w 1 -c1 212.21.92.27  | grep  transmitted"
#possitive_result="1 packets transmitted, 1 received, 0% packet loss"
# studio ping version
ping_cmd="ping -c1 212.21.92.27  | grep  transmitted"
possitive_result="1 packets transmitted, 1 packets received, 0% packet loss"
 




def clean(text):
	clean_text = text.replace("\,",",").replace("&","&amp;")
	return clean_text


def display(text):
	return "\n  ".join(wrap(text,70))

class UpcomingShowsControl(gtk.Label):
    def __init__(self):
        gtk.Label.__init__(self, "")  # invoke the super constructor
        self.seconds_togo=0
        self.text="loading..."
        gtk.timeout_add(1000, self.__update)  # a tick every second
        gtk.timeout_add(1000, self.__update_meta)
        self.__update_meta()

    def __update(self):
        self.set_markup('<span size="12000">%s</span>' % self.text)
        return gtk.TRUE
    

    def __update_meta(self):
        global ics_url,calendar
        up= {}
        if calendar == None:
            self.text="could not get latest information from server."
            return gtk.TRUE
        self.text="no show anounced"
        for show in calendar.components:
            try:
                next_show=parse(show.properties['DTSTART'].getContent().strip())
                next_show_end=parse(show.properties['DTEND'].getContent().strip())
            except:
                print "error parsing date:",show.properties['DTSTART'].getContent().strip()
                continue
            date_now=parse(time.strftime("%Y%m%dT%H%M%SZ"))

            if show.properties['LOCATION'].getContent().strip() != this_studio: 
                live = '<b>[preproduced] </b>'
            else: 
                live = '<b>[live]</b>'

            if next_show_end > date_now  and next_show <= date_now:
                ntext = ''
                # '' should be local location
                if show.properties['LOCATION'].getContent().strip() != this_studio: 
                    ntext +="<span size=\"36000\">this studio if off air!</span>\n"
                ntext +="%s - %s | %s\n" % (next_show.strftime("%H:%M"),next_show_end.strftime("%H:%M"),live)
                ntext += "  %s\n" % display(clean(show.properties['SUMMARY'].getContent().strip()))
                if show.properties['LOCATION'].getContent().strip() != '': 
                    ntext += "\n  %s\n" % display(clean(show.properties['LOCATION'].getContent().strip()))
                togo=(next_show_end-date_now)
                self.seconds_togo=togo.seconds
                ntext +="\n  Time left <b>%s</b>\n\n" % togo
                now=ntext
            elif next_show > date_now:
                ntext =''
                ntext +="%s - %s | %s\n" % (next_show.strftime("%H:%M"),next_show_end.strftime("%H:%M"),live)
                ntext += "  %s" % display(clean(show.properties['SUMMARY'].getContent().strip()))

                up[next_show]="%s\n"%ntext
                
        upcoming=""
        for key in up:
            upcoming +=up[key]

        self.text = "%s\n%s"%(now,upcoming);	
        return gtk.TRUE


class OnAirControl(gtk.Label):
	def __init__(self):
		gtk.Label.__init__(self, "initialize status.")  # invoke the super constructor
		self.set_justify(gtk.JUSTIFY_CENTER)
		gtk.timeout_add(1000, self._update_connection_status)

	def _update_connection_status(self):
		global ping_status
		if ping_status=="true":
			self.set_markup('<span size="24000">On Air</span>')
		else:
			self.set_markup('<span size="36000">NOT On Air</span>\n<b>- please check signal on FM -</b>')
		return gtk.TRUE


class CountdownControl(gtk.Label):
	def __init__(self):
		gtk.Label.__init__(self, "")  # invoke the super constructor
		gtk.timeout_add(1000, self.__update)  # a tick every second
		self.countdown=10
	
	def run(self):
		self.countdown=10
		self.show()

	def __update(self):
		self.set_markup('<span size="170000">%s</span>' % self.countdown)
		if self.countdown == -1:
			self.countdown=5
			self.hide()
		else:
			self.countdown = self.countdown - 1
		return gtk.TRUE


class ClockControl(gtk.Label):
    def __init__(self):
        gtk.Label.__init__(self, "")  # invoke the super constructor
        gtk.timeout_add(1000, self.__update)  # a tick every second
        
        
    def __update(self):
        date = strftime("%H:%M:%S")
        self.set_markup('<span size="72000">%s</span>' % date)
        return gtk.TRUE


class rebootStatus:
	def close_application(self, widget):
		gtk.mainquit()

	def __update(self):
		if self.upcomingShows.seconds_togo==10:
			self.countdown.run()
		return gtk.TRUE
	
	def __init__(self):
		gtk.timeout_add(1000, self.__update)  # a tick every second
		window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		window.set_resizable(gtk.TRUE)  
		window.connect("destroy", self.close_application)
		window.set_title("reboot.fm Statusmonitor")
		window.set_border_width(0)
		#Try to make the window full screen / needs something to put it on top.
		window.set_position(gtk.WIN_POS_CENTER)
		window.set_size_request(gtk.gdk.screen_width(),gtk.gdk.screen_height())
		
		vbox=gtk.VBox(gtk.FALSE, 0)
		vbox.show()
		window.add(vbox) 
		
		vbox.set_border_width(2)
		
		hbox1 = gtk.HBox(gtk.FALSE, 0)
		hbox2 = gtk.HBox(gtk.FALSE, 0)
		
		self.onAir=OnAirControl()
		self.onAir.show()



		clock = ClockControl()
		clock.show()
		vbox.pack_start(clock,gtk.FALSE,gtk.FALSE,0)
		vbox.pack_start(self.onAir,gtk.FALSE,gtk.FALSE,0)
		vbox.pack_start(hbox1,gtk.FALSE,gtk.FALSE,0)
		vbox.pack_end(hbox2,gtk.TRUE,gtk.TRUE,0)
		
		self.upcomingShows=UpcomingShowsControl()
		self.upcomingShows.show()
		hbox1.add(self.upcomingShows)


		self.countdown = CountdownControl()
		hbox2.add(self.countdown)

		hbox1.show()
		hbox2.show()
		window.show()

def _ical_update_thread():
    global calendar,irc_url
    calendar = None
    while run==1:
        try:
            ics_fh=urlopen(ics_url)
            calendar = pdi.parser.fromFileObject(ics_fh, ICalendar())
            ics_fh.close
        except:
            calendar == None
        sleep(10)

def _update_connection_status_thread():
    global ping_status
    ping_status="false"
    while run==1:
        f = os.popen(ping_cmd, 'r')
        for line in f.readlines():
            if re.search(possitive_result,line):           
                ping_status="true"
            else:
                ping_status="false"
            sleep(5)

run=1
if __name__ == "__main__":
    dto = socket.getdefaulttimeout()
    socket.setdefaulttimeout(4.0)
    calendar = None
    ping_status="false"
    t1=thread.start_new(_ical_update_thread, ())
    t2=thread.start_new(_update_connection_status_thread, ())
    rebootStatus()
    gtk.main()
    run=0
    socket.setdefaulttimeout(dto)
