#!/usr/bin/python

import twitter
import datetime
from time import strptime
from geopy import geocoders
from postcode import query_postcode
# from pprint import pprint


class TrafficNSW:
    def __init__(self, screen_name="TrafficNSW", expire = 3600):
        ''' (TrafficNSW, str, int) -> TrafficNSW

        RETURN :    an initiated TrafficNSW object.
        PARAMETER : 
            screen_name - the username in twitter
            expire - expire time (haven't been used yet)
        '''
        # self["name"] = screen_name
        self.id = screen_name
        self.text = []
        self.last_time_obtain_from_twitter = datetime.datetime(2000, 1, 1)
        self.expire = expire    # second

    def get_screen_name(self):
        return self.id

    def get_traffic_info(self):
        if self.text==[]:
            self.get_traffic_from_twitter()
        return self.text

    def get_latest_event(self):
        self.get_traffic_from_twitter()
        curr_status = self.text[0]
        return self.print_an_event(curr_status)

    '''
    STATIC FUNCTION     obtain_twitter_raw_data
    PARAMETER           id: the screen name of the twitter user_timeline
    RETURN              the raw timeline data got from twitter
    '''
    @staticmethod
    def obtain_twitter_raw_data(id = "TrafficNSW"):
        tw = twitter.Twitter(api_version='1')
        results = tw.statuses.user_timeline(screen_name = id)
        return results

    '''
    FUNCTION            parse_trafficnsw_twitter_entry
    PARAMETER           raw_data: the twitter timeline data
    RETURN              A list containing the individual event.
                        The single event is composed by a dictionary, including
                        time, location, event type.
    '''
    def parse_trafficnsw_twitter_entry(self, raw_data):
        events = []
        for status in raw_data:
            '''
            The following are the keys in TrafficNSW timeline raw data
            - u'user': user information
            - u'text': event information
            - u'created_at': event time
            '''
            str_event = status['text'].encode("utf-8")
            str_event_time = status['created_at'].encode("utf-8")

            '''
            Typical event is shown as follow
                Sydney Traffic EMERGENCY ROAD WORKS - TURRAMURRA Pacific Hwy \
                at Kissing Point Rd #sydtraffic #trafficnetwork
            Before '-', it is event type; after that, it is event location.
            I also need to remove "Sydney Traffic" and 
                "#sydtraffic #trafficnetwork" signs.
            '''
            event_type = str_event[len('Sydney Traffic '):str_event.find(' -')]

            event_location = str_event[ str_event.find('-')+2 : \
                                        str_event.find(' #')]

            # ''' 
            # The following part uses geopy to process location into geocode.
            # '''
            # geo = geocoders.GoogleV3()
            # try:
            #     event_geo = geo.geocode(event_location)
            # except:
            #     event_geo = None

            # if event_geo != None:
            #     # print "%s: %.5f, %.5f" % (event_geo[0], event_geo[1][0], event_geo[1][1])
            #     # print event_geo
            #     event_street = event_geo[0].encode("utf-8").split(',')[0]
            #     event_suburb = event_geo[0].encode("utf-8").split(',')[1].split()[:-2]
            #     event_postcode = event_geo[0].encode("utf-8").split(',')[1].split()[-1]
            #     event_cord = event_geo[1]
            # else: 
            #     event_suburb = ""
            #     for i in event_location.split():
            #         if i==i.upper():
            #             event_suburb += i + " "
            #     event_suburb.strip()        # Remove the last ' '
            #     event_street = event_location.lstrip(event_suburb).strip()
            #     event_postcode = None
            #     event_cord = None

            gcode = query_postcode(event_location)

            '''
            Data is shown as 
                Tue Apr 09 01:50:04 +0000 2013
            Please note it is UTC time. So, we need to convert it into local 
            (Sydney) time.
            Because striptime has a bug in parse '%z', I have to remove +0000 \
            from the string
            '''
            str_event_time = str_event_time.replace("+0000 ", "")
            utc_time = datetime.datetime.strptime(str_event_time, \
                '%a %b %d %H:%M:%S %Y')
            event_time = utc_time + datetime.timedelta(hours=10)

            event = {}
            event['time'] = event_time
            event['type'] = event_type
            event['suburb'] = gcode['suburb']
            event['street'] = gcode['street']
            event['postcode'] = gcode['postcode']
            event['coordinate'] = gcode['cord']

            events.append(event)

        return events

    """

    """
    def get_traffic_from_twitter(self):

        '''
        The following block is to test if the twitter query happened in the
        last 2 minutes. If so, just return. Otherwise, it will do a new query.
        '''
        current_time = datetime.datetime.now()
        time_diff = (current_time - self.last_time_obtain_from_twitter).seconds
        if time_diff < 120:
            # print "No change"
            return
        else:
            self.last_time_obtain_from_twitter = current_time
            # print self.last_time_obtain_from_twitter
        self.text = []

        raw_data = TrafficNSW.obtain_twitter_raw_data()
        results = self.parse_trafficnsw_twitter_entry(raw_data)

        for status in results:
            self.text.append(status)

        return results

    """

    """
    def get_traffic_in_minutes(self, minutes = 60):
        seconds = minutes * 60
        current_time = datetime.datetime.now()

        self.get_traffic_from_twitter()
        output = []

        for event in self.text:
            time_diff = (current_time - event["time"]).seconds
            if time_diff <= seconds:
                output.append(event)

        return output


    def __str__(self):
        if self.text == []:
            return "No event in record."

        return "Current event: %(time)s, %(street)s, %(suburb)s, %(type)s. " \
        % ({'time': str(self.text[0]['time']), \
            'street': self.text[0]['street'], \
            'suburb': self.text[0]['suburb'], \
            'type': self.text[0]['type'] })


# The following part is used for test
if __name__ == '__main__':
    '''
    2 kinds of tests could be done in the following part.
    (1) doctest
        It would test every function with standard comments in the file. This
        method is not good for Class.
    (2) unitest
        It will run some written script.
    '''

    # # DOCTEST
    # import doctest
    # doctest.testmod()

    # # UNITEST
    # import unitest

    # class TestTrafficNSW(unitest.TestCase):
    #     ''' Test functions in TrafficNSW. '''

    #     # ALL test functions should start as 'test_'
    #     def test_xxx(self):
    #         # xxx
    #         actual = xxx_function
    #         expected = xxx_exp
    #         self.assertEqual(expected, actual)

    tnsw = TrafficNSW()

    # tnsw.obtain_traffic_from_twitter()
    # tnsw.obtain_traffic_from_twitter()

    # tnsw.get_latest_event()
    tnsw.print_events()
