# Copyright (c) 2015 Victor Vasiliev
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import datetime
import glob
import jinja2
import re
import os
import os.path
import shutil
import yaml

script_base = os.path.dirname(os.path.realpath(__file__))

### CONFIGURATION STARTS HERE
year = 2017

class_list_path = os.path.join(script_base, 'classes.yaml')
template_base = os.path.join(script_base, 'template')
static_dir = os.path.join(script_base, 'static')
output_dir = os.path.join(script_base, 'output')
### CONFIGURATION ENDS HERE

def render_email(addr):
    """
    Obfuscate the email address before it is rendered on the web page.
    This currently uses the same way old IAP website did.
    """

    return addr.replace('@', ' at ').replace('.', ' dot ')

def parse_time(timestr):
    """
    Parses 24-hour time with minute precision.
    """
    hour, minute = map(int, timestr.split(":"))
    return datetime.time(hour, minute)

class Class(object):
    def __init__(self, obj):
        self.id = obj['id']
        self.title = obj['title']
        if type(obj['teachers'] == list):
            self.teachers = obj['teachers']
        else:
            self.teachers = [obj['teachers']]
        self.description = obj['description']
        self.attendance = obj['attendance']
        self.prereqs = obj['prereqs']
        self.dates = obj['dates']
        self.contact_person = obj['contact_person'] if 'contact_person' in obj else None
        self.contact_email = obj['contact_email']

        for i, date in enumerate(self.dates):
            if not all(x in date for x in {'start', 'end', 'date', 'location'}):
                raise ValueError("Incomplete date for event %s" % self.id)
            if type(date['date']) != datetime.date:
                raise ValueError("Malformed date for event %s" % self.id)
            self.dates[i]['start'] = parse_time(date['start'])
            self.dates[i]['end'] = parse_time(date['end'])

    def render_contact(self):
        contact = render_email(self.contact_email)
        if self.contact_person:
            contact = "%s, %s" % (self.contact_person, contact)
        return contact

    def render_teachers(self):
        return ", ".join(self.teachers)

    def render_dates(self):
        date_list = []
        for d in self.dates:
            date = d['date'].strftime('%a %b %d')
            start = d['start'].strftime('%I:%M%p').lower()
            end = d['end'].strftime('%I:%M%p').lower()
            s = "%s %s &ndash; %s in %s" % (date, start, end, d['location'])
            date_list.append(s)

        if len(date_list) > 1:
            return "<ul><li>" + "</li><li>".join(date_list) + "</li></ul>"
        else:
            return date_list[0]

    def description_paragraphs(self):
        paragraphs = []

        for text in self.description.strip().split("\n"):
            text = text.replace("&", "&amp;")
            text = text.replace("<", "&lt;")
            text = text.replace(">", "&gt;")

            url_re = r"(https?://[a-z0-9./\-_#=]+)"
            text = re.sub(url_re, "<a href=\"\\1\">\\1</a>", text)

            paragraphs.append(text)

        return paragraphs

# Load templates.
env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_base), autoescape=True)

# Load the list of classes.
with open(class_list_path, 'r') as f:
    classes = [Class(obj) for obj in yaml.load_all(f)]

# Prepare template rendering parameters.
parameters = {}
parameters['year'] = year
parameters['classes'] = classes

# Render main HTML page.
print "Generating main website HTML..."
index_html_path = os.path.join(output_dir, 'index.html')
with open(index_html_path, 'w') as f:
    f.write(env.get_template('index.html').render(**parameters).encode('utf-8'))

# Copy static files.
print "Copying static files..."
static_files = glob.glob(static_dir + '/*')
for path in static_files:
    shutil.copy(path, output_dir)
