from collections import defaultdict
from datetime import datetime
from hashlib import sha1
import hmac
import httpx
import os

dev_id = os.environ['PTV_USER_ID']
api_key = os.environ['PTV_API_KEY']

def sign(request):
    request += '&' if ('?' in request) else '?'
    request += 'devid='
    request += dev_id
    hashed = hmac.new(api_key.encode(), request.encode(), sha1)
    return f'https://timetableapi.ptv.vic.gov.au{request}&signature={hashed.hexdigest().upper()}'

def fetch(path):
    res = httpx.get(sign(path))
    try:
        res.raise_for_status()
    except:
        try:
            print(res.json())
        except:
            pass
        raise
    return res.json()

# Lilydale route 9 (type 0) (dir 1 in, 8 out) (stop 1229)
# Belgrave route 2 (type 0) (dir 1 in, 2 out) (stop 1229)
# 109 route 722 (type 1) (dir 2 E, 3 W) (stop 2415 E, 2460 W)
# 70 route 940 (type 1) (dir 28 E, 29 W) (stop 2161 E, 2162 W)
# 766 route 15800 (type 2) (dir 13 N, 207 S) (stop 17861)
# 612 route 13024 (type 2) (dir 13 N, 158 S) (stop 17861)

class Route:
    def __init__(self, name, route_id, route_type_id, directions, stops):
        self.name = name
        self.route_id = route_id
        self.route_type_id = route_type_id
        self.directions = directions
        self.stops = stops

local_routes = [
    Route('Lilydale', 9    , 0, [(1, 'in'), (8, 'out')]   , [1229]      ),
    Route('Belgrave', 2    , 0, [(1, 'in'), (2, 'out')]   , [1229]      ),
    Route('109'     , 722  , 1, [(2, 'E'), (3, 'W')]      , [2415, 2460]),
    Route('70'      , 940  , 1, [(28, 'E'), (29, 'W')]    , [2415, 2460]),
    Route('766'     , 15800, 2, [(13, 'N'), (207, 'S')]   , [17861]     ),
    Route('612'     , 13024, 2, [(13, 'N'), (158, 'S')]   , [17861]     ),
]

def fetch_departures(stop_id, route_type_id):
    deps = fetch(f'/v3/departures/route_type/{route_type_id}/stop/{stop_id}')['departures']
    for dep in deps:
        for key in ['estimated_departure_utc', 'scheduled_departure_utc']:
            if dep[key]:
                dep[key] = datetime.fromisoformat(dep[key])
    deps.sort(key=lambda dep: dep['estimated_departure_utc'] or dep['scheduled_departure_utc'])
    return deps

def get_departure_data():
    by_route_type = defaultdict(list)
    for route_type, stop in set((r.route_type_id, s) for r in local_routes for s in r.stops):
        by_route_type[route_type] += fetch_departures(stop, route_type)
    return by_route_type
