"""scottylabs.py

Interface to the ScottyLabs backend server.

Sample of the current data format:
[ { "_id":"6057fa3d3e90ef57aac3a6c1",
    "title":"a",
    "email":"sample@email.com",
    "author":"b",
    "frame_rate":0.5,
    "img_url":"https://drive.google.com/uc?id=1HUfWKyi9wy4xQmo0TY21x5KJAFcmlfbf",
    "createdAt":"2021-03-22T02:00:29.039Z"},

  { "_id":"6057fceb617ec3001511a625",
    "title":"a",
    "email":"sample@email.com",
    "author":"b",
    "frame_rate":0.5,
    "img_url":"https://drive.google.com/uc?id=1qDWfI6bzEuI-8Tqe5r5_nD3oiwsi8tH2",
    "createdAt":"2021-03-22T02:11:55.723Z"},
 ]
"""

import urllib.request
import json
import logging

#================================================================

# Utility function for sanitizing Unix filenames.  The name components include a
# title and email address.  This simply replaces characters unsuitable for
# filenames.  Given that titles can contain any text and email addresses can
# have quoted text, this will invariably corrupt some inputs.

invalid_chars = "/\u2423\r\n\000\010\033\177"
replacements = "".join(['_'] * len(invalid_chars))
fn_table = str.maketrans(invalid_chars, replacements)

def sanitize_fn_string(input):
    return input.translate(fn_table)

#================================================================
class Submissions(object):
    def __init__(self, config):
        logging.debug("Entering Submissions.__init__ and initializing superclasses")
        super(Submissions, self).__init__()

        # this should be stored in a config file and not submitted to git
        self.backend_url = config.scotty_backend_url
        return

    def fetch_submission_metadata(self):
        try:
            req = urllib.request.urlopen(self.backend_url)
            html = req.read()
            data = json.loads(html)
            return data

        # some possible exceptions: urllib.error.HTTPError
        except:
            logging.error('Failed to fetch ScottyLabs Submissions metadata.')
            return None

    def get_all_image_ids(self, data):
        """Retrieve the Google Drive identifiers for all images in a metadata set."""
        return [item['img_url'][31:] for item in data]

    def find_record(self, data, image_id):
        for item in data:
            if item['img_url'][31:] == image_id:
                return item
        return None

    def make_filename(self, record):
        # save the rate metadata as an integer tempo
        frame_rate = record['frame_rate']
        tempo = int(60.0 / frame_rate) if frame_rate != 0.0 else 120
        tempo = min(max(tempo, 1), 1800)

        # sanitize each metafield to be suitable for inclusion in a filename
        sanitized_title = sanitize_fn_string(record['title'])
        sanitized_email = sanitize_fn_string(record['email'])

        # use a Unicode U+2423 'Open Box' character as the field separator
        name = '\u2423'.join((sanitized_title, sanitized_email, "%d.png" % tempo))
        return name
