# coding=UTF-8
from urllib2 import Request, urlopen, URLError
from urllib import urlencode
from etmParsers import *
from xml.etree.ElementTree import ElementTree, tostring
from HTMLParser import HTMLParser
import socket
import calendar
import wx.html
import wx.calendar
lcl = locale.getdefaultlocale()
today = datetime.datetime.now()


city = state = place = ""
lat = lon = []

s_regex = re.compile(' ', re.M|re.L|re.U)
y_regex = re.compile(r'\{.*\}units$')

def direction(deg):
    points = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
    index = (int(deg)*100+1125)/2250
    if index == 16:
        return points[0]
    else:
        return points[index]

def getWeather():
    ret = []
    frcst = []
    timeout = 10
    socket.setdefaulttimeout(timeout)

    url = 'http://xml.weather.yahoo.com/forecastrss?p=%s' \
            % weatherlocation
    req = Request(url)
    try:
        response = urlopen(req)
    except URLError, e:
        if hasattr(e, 'reason'):
            msg = """\
We failed to reach the weather server at 
    %s
Reason: %s.""" % (url, e.reason)
        elif hasattr(e, 'code'):
            msg = """\
The weather server at 
    %s 
couldn\'t fulfill the request.
Error code: %s.""" % (url, e.code)
        return(0, msg)

    # connection is fine
    tree = ElementTree()
    response = urlopen(req)
    tree.parse(response)
    channel = tree.find("channel")
    data = {}
    if not channel is None:
        elements = channel.getchildren()
        # elements = tree.list(channel)
        for element in elements:
            if not element is None:
                m = y_regex.match(element.tag)
                if m:
                    group = 'units:'
                else:
                    group = ''
                items = element.items()
                for item in items:
                    if item[0] in ['city', 'region', 'country', 'temperature',
                        'distance', 'pressure', 'speed', 'direction', 'chill',
                            'pressure', 'rising', 'visibility', 'humidity',
                            'sunrise', 'sunset']:
                            data["%s%s" % (group, item[0])] = item[1]
    title = "%s %s" % (weather, data['city'])
    if data['region']:
        title += ", %s" % data['region']
    elif data['country']:
        title += ", %s" % data['country']
    channelitem = channel.find("item")
    # channelitem = tree.getroot()
    if channelitem is not None: 
        elements = channelitem.getchildren()
        first = True
        second = False
        temperature = 0
        for element in elements:
            if element is not None:
                items = element.items()
                hash = {}
                string = ""
                for item in items:
                    if item[0] in ['day', 'date', 'text', 'temp', 'high', 'low']:
                        hash[item[0]] = item[1]
                        if item[0] == 'temp':
                            temperature = item[1]
                if hash:
                    if first:
                        ret.append(title)
                        ret.append("    %s: %s" %
                            (current_conditions, hash['date']))
                        keys = ['text', 'temp']
                        first = False
                        second = True
                    elif second:
                        keys = ['day', 'date', 'text', 'temp']
                        string = "        wind "
                        if data['speed'] and float(data['speed']) > 0:
                            for key in ['direction', 'speed', 'chill']:
                                if key in data:
                                    if key == 'direction':
                                        string += "%s, " % (
                                            direction(data[key]))
                                    elif key == 'chill' and \
                                        data['chill'] != temperature:
                                        string += ", %s %s%s" % (
                                            chill,
                                            data['chill'],
                                            data['units:temperature'])
                                    elif key == 'speed':
                                        string += "%s %s %s" % (
                                            key,
                                            data[key],
                                            data['units:speed'])
                        else:
                            string += "calm"
                        ret.append(string)
                        string = "        "
                        for key in ['humidity', 'visibility', 'pressure',
                            'rising']:
                            if key in data:
                                if key == 'pressure':
                                    string += "%s %s %s, " % (
                                        key,
                                        data[key],
                                        data['units:pressure'])
                                elif key == 'visibility':
                                    string += "%s %s %s, " % (
                                        key,
                                        data[key],
                                        data['units:distance'])
                                elif key == 'rising':
                                    if data['rising'] == '1':
                                        string += rising
                                    elif data['rising'] == '-1':
                                        string += falling
                                    else:
                                        string += constant
                                else:
                                    string += "%s %s, " % (key, data[key])
                        ret.append(string)
                        string = "        "
                        for key in ['sunrise', 'sunset']:
                            if key in data:
                                if key == 'sunrise':
                                    string += "%s %s, " % (key, data[key])
                                else:
                                    string += "%s %s" % (key, data[key])
                        ret.append(string)
                        #### Forecast ####
                        ret.append("    %s" % forecast)
                        second = False
                    string = "        "
                    fst = ""
                    for key in keys:  # keys = ['day', 'date', 'text', 'temp']
                        if key in hash:
                            if key == 'day':
                                string += "%s, " % hash[key]
                            elif key == 'date':
                                string += "%s: " % hash[key]
                            elif key == 'temp':
                                string += "%s%s" % (
                                    hash[key], data['units:temperature'])
                                fst += "%s%s" % (
                                    hash[key], data['units:temperature'])
                            else:
                                string += "%s, " % hash[key]
                                fst += "%s, " % hash[key]
                    for key in ['high', 'low']:
                        if key in hash:
                            if key == 'high':
                                string += "%s %s%s, " % (
                                    key,
                                    hash[key],
                                    data['units:temperature'])
                                fst += "%s %s%s, " % (
                                    key,
                                    hash[key],
                                    data['units:temperature'])
                            elif key == 'low':
                                string += "%s %s%s" % (
                                    key,
                                    hash[key],
                                    data['units:temperature'])
                                fst += "%s %s%s" % (
                                    key,
                                    hash[key],
                                    data['units:temperature'])
                    ret.append(string)
                    frcst.append(fst)
    return(1,ret)


def getForecast():
    f = []
    ok, l = getWeather()
    if ok:
        f.append(l[1].strip().split('s: ')[1])
        f.append(l[2].strip())
        for i in [-2, -1]:
            f.append(l[i].split(':')[1].strip())
    else:
        f = l
    return(ok, f)


class MyHTMLParser(HTMLParser):

    def __init__(self):
        HTMLParser.__init__(self)
        self.capture = False
        self.pre = False
        self.more = True
        self.output = []
        self.para = ''
        self.skip = False

    def handle_starttag(self, tag, attrs):
        if tag in ['p', 'pre']:
            if tag == 'pre':
                self.pre = True
            self.capture = True
        elif tag == "strong":
            self.output.append('')
        elif tag in ['hr', 'a']:
            self.more = False

    def handle_endtag(self, tag):
        if tag in ['p', 'pre']:
            if tag == 'pre':
                self.pre = False
                self.output.append('')
            else:

                l = text_wrap(self.para, width=70)
                self.output.extend(l)
                self.output.append('')
                self.para = ''
            self.capture = False

    def handle_data(self, text):
        if self.more and self.capture:
            if self.pre:
                text = text.rstrip()
                if text:
                    self.skip = False
                    out = []
                    parts = text.split('\n')
                    for part in parts:
                        p = part.rstrip()
                        if p:
                            self.output.append("%s\n" % p)
                else:
                    self.skip = True
            else:
                l = text.split()
                self.para += " ".join(l)

    def output(self):
        return self.output

def getSunMoon(d=None):
    import socket
    timeout = 10
    socket.setdefaulttimeout(timeout)
    data = {}
    if len(location) == 2:
        ffx = 1
        data['place'] = location[0]
        data['st'] = location[1]
    elif len(location) == 7:
        ffx = 2
        data['place'] = location[0]
        if location[1].upper() == 'E':
            data['xx0'] = 1
        elif location[1].upper() == 'W':
            data['xx0'] = -1
        data['xx1'] = location[2]
        data['xx2'] = location[3]

        if location[4].upper() == 'N':
            data['yy0'] = 1
        elif location[4].upper() == 'S':
            data['yy0'] = -1
        data['yy1'] = location[5]
        data['yy2'] = location[6]

        if time.localtime().tm_isdst:
            utcoffset = time.altzone/3600
        else:
            utcoffset = time.timezone/3600
        if utcoffset < 0:
            # east of Greenwich
            data['zz0'] = 1
            data['zz1'] = -utcoffset
        else:
            # west of Greenwich
            data['zz0'] = -1
            data['zz1'] = utcoffset
    else:
        return (0, 'There is a problem with the setting for \'location\' in ~/.etmrc.')

    if d:
        year, month, day = duparse(d).strftime("%Y %m %d").split()
    else:
        year, month, day = datetime.datetime.now().strftime("%Y %m %d").split()

    # this hack is needed to put FFX and xxy first - otherwise usno uses latitude degrees as the year.
    url_data = "FFX=%s&xxy=%s&xxm=%s&xxd=%s&" % (ffx, year, month, day)
    url_data += urlencode(data)
    url = 'http://aa.usno.navy.mil/cgi-bin/aa_pap.pl'
    req = Request(url)
    try:
        response = urlopen(req, url_data)
    except URLError, e:
        if hasattr(e, 'reason'):
            msg = """\
We failed to reach a server.
Reason: %s.""" % e.reason
        elif hasattr(e, 'code'):
            msg = """\
The server couldn\'t fulfill the request.
Error code: %s.""" % e.code
        return(0, msg)
    # connection is fine
    data = response.read().strip()
    data = s_regex.sub('.', data)
    myparser = MyHTMLParser()
    myparser.feed(data.encode('UTF-8'))
    myparser.close()
    return(0, '\n'.join([x.rstrip() for x in myparser.output]))

def calyear(advance=0):
    if sundayfirst:
        week_begin = 6
    else:
        week_begin = 0
    # hack to set locale on darwin, windoz and linux
    if mac:
        lcl = locale.getdefaultlocale()
        c = calendar.LocaleTextCalendar(week_begin, lcl[0])
    elif windoz:
        locale.setlocale(locale.LC_ALL, '')
        lcl = locale.getlocale()
        c = calendar.LocaleTextCalendar(week_begin, lcl)
    else:
        lcl = locale.getdefaultlocale()
        c = calendar.LocaleTextCalendar(week_begin, lcl)
    cal = []
    y = int(today.strftime("%Y"))
    m = 1
    d = 1
    y += advance
    for i in range(12):
        cal.append(c.formatmonth(y,m).split('\n'))
        m += 1
        if m > 12:
            y += 1
            m = 1
    s = []
    for r in range(0,12,3):
        l = max(len(cal[r]), len(cal[r+1]), len(cal[r+2]))
        for i in range(3):
            if len(cal[r+i]) < l:
                for j in range(len(cal[r+i]), l+1):
                    cal[r+i].append('')
        for j in range(l):
            s.append((u"  %-20s    %-20s    %-20s" %
                (cal[r][j], cal[r+1][j], cal[r+2][j])).encode())
    return(s)


# class ETMcal(wx.Dialog):
class ETMcal(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, 'etm', size=(225,225))
        self.parent = parent
        self.parent.selecteddate = None
        sd = wx.DateTime_Now()
        cal = wx.calendar.CalendarCtrl(self, -1, date=sd,
                size = (-1, -1),
                style = wx.calendar.CAL_SHOW_HOLIDAYS
                    | wx.calendar.CAL_SUNDAY_FIRST
                    | wx.calendar.CAL_SHOW_SURROUNDING_WEEKS
                    )
        self.cal = cal
        self.Bind(wx.calendar.EVT_CALENDAR_SEL_CHANGED, 
                self.OnCalSelChanged, id=cal.GetId())
        self.Bind(wx.calendar.EVT_CALENDAR, self.OnCalSelected, 
                id=cal.GetId())

        ok = wx.Button(self, wx.ID_OK, "OK")
        ok.SetDefault()
        self.Bind(wx.EVT_BUTTON, self.OnQuit, id=ok.GetId())

        # cancel = wx.Button(self, wx.ID_CANCEL, "CANCEL")
        # self.Bind(wx.EVT_BUTTON, self.OnCancel, id=cancel.GetId())

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(cal, 0, wx.EXPAND | wx.ALL, 5)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        # hbox.Add(cancel, 1, wx.ALIGN_RIGHT | wx.ALL, 5)
        hbox.Add(ok, 1, wx.ALIGN_RIGHT | wx.ALL, 5)
        vbox.Add(hbox, 0, wx.ALIGN_CENTER)
        self.SetSizerAndFit(vbox)
        self.Layout()

    def OnCalSelChanged(self, event):
        self.parent.selecteddate = event.GetDate().Format("%Y-%m-%d")

    def OnCalSelected(self, event):
        self.parent.selecteddate = event.GetDate().Format("%Y-%m-%d")
        self.Destroy()

    def OnCancel(self, event):
        self.parent.selecteddate = None
        self.Destroy()

    def OnQuit(self, event):
        self.Destroy() 


class ETM12cal(wx.Frame):
    def __init__(self, size=wx.DefaultSize):
        wx.Frame.__init__(self, None, -1, 'etm', size=(560, 680))
        self.html = wx.html.HtmlWindow(self)
        if "gtk2" in wx.PlatformInfo:
            self.html.SetStandardFonts(htmlfont+4, '', '')
        else:
            self.html.SetFonts('', '', [i for i in range(htmlfont,
                htmlfont+13,2)])
        self.html.SetRelatedFrame(self, "%s")
        button = wx.Button(self, wx.ID_OK)
        button.SetDefault()
        self.printer = wx.html.HtmlEasyPrinting()
        self.printer.SetFonts('', '', [i for i in range(htmlprintfont,
            htmlprintfont+13, 2)])
        self.printdata = self.printer.GetPrintData()
        self.printdata.SetColour(False)
        self.Bind(wx.EVT_BUTTON, self.OnQuit, button)
        self.Bind(wx.EVT_CHAR, self.OnChar)
        self.html.Bind(wx.EVT_CHAR, self.OnChar)
        self.cal_advance = 0
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.html, 1, wx.EXPAND | wx.ALL, 4)
        sizer.Add(button, 0, wx.ALIGN_CENTER | wx.BOTTOM, 4)
        self.SetSizer(sizer)
        self.Layout()
        self.show_cal()

    def SetPage(self, html):
        self.page = html
        self.html.SetPage(html)

    def OnChar(self, event):
        keycode = event.GetKeyCode()
        if keycode in [17, 27]:     # Ctrl-Q, Escape quit
            self.OnQuit(event)
        elif keycode == 16:         # Ctrl-P print
            self.OnPrint(event)
        elif keycode == 25:         # Ctrl-Y yank
            self.OnSelect(event)
        elif keycode in [wx.WXK_UP]:
            self.cal_advance -= 1
            self.show_cal()
        elif keycode in [wx.WXK_DOWN]:
            self.cal_advance += 1
            self.show_cal()
        elif keycode in [wx.WXK_HOME]:
            self.cal_advance = 0
            self.show_cal()
        else:
            event.Skip()

    def show_cal(self):
        if self.cal_advance < 0:
            bgcolor = cal_pastcolor
        elif self.cal_advance == 0:
            bgcolor = cal_currentcolor
        else:
            bgcolor = cal_futurecolor
        html = """\
<title>etm calendar</title>
<body text="%s" bgcolor="%s">
<pre>
%s</pre>
</body>
""" % (fgcolor, bgcolor,  "\n".join(calyear(self.cal_advance)))
        # self.html = html
        # self.prnt = html
        self.SetPage(html)
        self.Refresh()


    def OnPrint(self, event):
        self.printer.SetHeader(
          '<center><font size="+1">%s</font></center>' %
          self.html.GetOpenedPageTitle())
        self.printer.SetFooter(
                '<center>Page @PAGENUM@ of @PAGESCNT@</center>')
        self.printer.PrintText(self.page)

    def OnSelect(self, event):
        s = self.html.SelectionToText()
        if s:
            self.do = wx.TextDataObject()
            self.do.SetText(s)
            if wx.TheClipboard.Open():
                wx.TheClipboard.SetData(self.do)
                wx.TheClipboard.Close()
            self.html.SetPage(self.page)

    def OnQuit(self,event):
        self.Destroy()


class App(wx.App):
    def OnInit(self):
        self.frame = ETM12cal()
        self.frame.Show(True)
        self.SetTopWindow(self.frame)
        return True

def main1():
    app = App(redirect=False)
    app.MainLoop()

def main2():
    app = wx.App()
    dialog = ETMcal()
    result = dialog.ShowModal()
    if result == wx.ID_OK and dialog.selecteddate:
        return dialog.selecteddate
    else:
        return result

if __name__ == "__main__":
    import sys
    location = ['Chapel Hill', 'NC']

    # location = ['Home', 'W',79,0, 'N',35,54]
    l = [None]
    if len(sys.argv) > 1:
        l.append(" ".join(sys.argv[1:]))
    for d in l:
        out = getSunMoon(d)
        print "for date: %s" % d
        print "\n".join(out)

    # http://xml.weather.yahoo.com/forecastrss?p=USNC0105&u=f
    # http://xml.weather.yahoo.com/forecastrss?p=USNC0105hr&u=f
    # weatherlocation = 'USNC0105&u=f' # Chapel Hill
    # location = 'USNC0105&u=c' # Chapel Hill celcius
    # location = 'FRXX2071&u=c' # Paris
    # location = 'UKXX1822&u=f' # London
    # location = 'GMXX0008&u=c' # Berlin
    ok, l = getWeather()
    if ok:
        print "\n".join(l)
    else:
        print l
    ok, l = getForecast()
    if ok:
        print "\n".join(l)
    else:
        print l# coding=UTF-8

    print calyear()
    main1()
    res = main2()
    print res