#!/usr/bin/env python

import os
import sys
import time
import urllib.request
import yaml

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

# The key is the url
# The value holds the content and the timestamp
file_cache = {}
file_cache_ttl = 60

mapper_file = ''
with open('/var/openfaas/secrets/url-mapper-file', 'r') as f:
    mapper_file = f.read().strip()

def get_url_content(url):
    if url in file_cache:
        cache_entry = file_cache[url]
        if cache_entry['timestamp'] + file_cache_ttl > time.time():
            return cache_entry['content']

    try:
        response = urllib.request.urlopen(url)
        targets = yaml.safe_load(response.read())
    except Exception as e:
        eprint("Failed to load URL mapper file: %s" % e)
        return None

    file_cache[url] = {
        'content': targets,
        'timestamp': time.time()
    }
    return targets

def get_dict_entry_fallback(d, key, fallback):
    if key and key in d:
        return d[key]
    if key.isnumeric() and int(key) in d:
        return d[int(key)]
    if fallback in d:
        return d[fallback]
    return d.get('_default', None)

def get_entry(args, targets):
    while args:
        arg = args.pop(0)
        if not arg:
            continue

        # Fallback to _404 if the key is not found
        targets = get_dict_entry_fallback(targets, arg, '_404')
        if isinstance(targets, dict):
            continue
        return targets, args

    # Try to match an index entry
    return get_dict_entry_fallback(targets, '', '_index'), args

def get_entry_for_url(url, args):
    targets = get_url_content(url)
    if not targets:
        return None

    entry, args = get_entry(args, targets)
    if not entry:
        return None
    if entry.startswith('include:'):
        entry = entry.split(':', 1)[1]
        return get_entry_for_url(entry, args)
    return entry

    
def handle(event, context):

    args = event.path.split('/')

    url = get_entry_for_url(mapper_file, args)


    if not url:
        return {
            "statusCode": 404,
            "body": "URL not found"
        }

    return {
        "statusCode": 302,
        "body": url,
        "headers": {
            "Location": url
        }
    }