#!/usr/bin/env python3

import sys
import os
import shutil
import html

import yaml


def read(path):
    with open(path) as f:
        return f.read()

def write(path, text):
    with open(path, 'w') as f:
        f.write(text)

def load_settings(settings_file):
    with open(settings_file) as f:
        settings = {name: value
                    for name, value
                    in (line.split('=', 1) for line in
                        f.read().strip().split('\n'))}
    return settings

def load_media(media_file):
    with open(media_file) as f:
        c = yaml.load(f, Loader=yaml.FullLoader)
    c['date'] = c['date']
    c['ident'] = ident(media_file)
    return c

def ident(media_file):
    return os.path.splitext(os.path.split(media_file)[1])[0]

def thumbnail_path(name):
    return os.path.join(name, 'thumbnail.jpg')

def thumbnail_url(link):
    return link + 'thumbnail.jpg'

def setup_directory_structure(settings, base_dir, template_dir):
    site_new_dir = os.path.join(base_dir, 'site-new')
    shutil.rmtree(site_new_dir, ignore_errors=True)
    os.mkdir(site_new_dir)

    style = read(os.path.join(template_dir, 'style.css'))
    style_out = style.replace('{', '{{').replace('}', '}}') \
                     .replace('[', '{').replace(']', '}').format(**settings)
    style_new_file = os.path.join(site_new_dir, 'style.css')
    write(style_new_file, style_out)

    shutil.copy(os.path.join(template_dir, 'favicon.png'), site_new_dir)

    return site_new_dir

def publish_new_site(site_dir, site_new_dir):
    shutil.rmtree(site_dir, ignore_errors=True)
    shutil.move(site_new_dir, site_dir)

def generate_index_page(out_dir, base_html, section_html, medias):
    sections = [generate_video_section_html(section_html, media)
                for media in medias]

    all_sections = '\n'.join(sections)
    html_out = base_html.format(content=all_sections,
                                style_url='style.css')

    out_file = os.path.join(out_dir, 'index.html')
    write(out_file, html_out)

def generate_video_section_html(section_html, media):
    title = media['title']
    link = media['ident'] + '/'
    thumbnail = thumbnail_url(link)

    html_out = section_html.format(
        title=html.escape(title),
        thumbnail=thumbnail, link=link)
    return html_out

def iframe_video(file_src):
    return '''\
    <iframe width="759" height="427" src="{url}" frameborder="0" allowfullscreen>
    </iframe>
'''.format(url=file_src)

def url_video(url):
    return '''\
<video src="{url}" controls height="427">
Your browser cannot play this video.  You can download it here instead:
<a href="{url}">{url}</a>
</video>
'''.format(url=url)

def extern_video(file_src):
    url = 'https://media-metanohi-name.eu-central-1.linodeobjects.com/media/' + file_src
    return url_video(url)

def youtube_video(file_src):
    yt_id = file_src
    return '''\
<iframe type="text/html" width="760" height="427"
        src="https://www.youtube.com/embed/{yt_id}?controls=2"
        allowfullscreen frameborder="0">
</iframe>
'''.format(yt_id=yt_id)

def generate_video_page(base_dir, out_dir, base_html, showing_html, media):
    title = media['title']
    date = str(media['date'])
    description = media['description'].rstrip()
    name = media['ident']
    video_dir = os.path.join(out_dir, name)
    os.mkdir(video_dir)
    thumbnail_file = thumbnail_path(video_dir)
    thumbnail_file_local = os.path.join(
        base_dir, 'thumbnails-small', name + '.jpg')
    shutil.copyfile(thumbnail_file_local, thumbnail_file)

    file_type, file_src = media['file'].split(':', 1)
    actions = {
        'extern': extern_video,
        'url': url_video,
        'iframe': iframe_video,
        'youtube': youtube_video
    }
    video_html = actions[file_type](file_src)

    html_inner = showing_html.format(
        title=html.escape(title),
        year=date[:4],
        description=html.escape(description),
        video=video_html)
    html_out = base_html.format(content=html_inner,
                                style_url='../style.css')

    out_file = os.path.join(video_dir, 'index.html')
    write(out_file, html_out)

def main():
    script_dir = os.path.dirname(__file__)
    settings_file = os.path.join(script_dir, 'settings')
    settings = load_settings(settings_file)
    base_dir = os.path.split(script_dir)[0]

    template_dir = os.path.join(base_dir, 'template')
    base_html = read(os.path.join(template_dir, 'base.html'))
    section_html = read(os.path.join(template_dir, 'section.html'))
    showing_html = read(os.path.join(template_dir, 'showing.html'))

    media_dir = os.path.join(base_dir, 'media')
    media_files = [os.path.join(media_dir, media_file)
                   for media_file in os.listdir(media_dir)]
    medias = [load_media(media_file) for media_file in media_files]
    medias.sort(key=lambda m: (str(m['date']), m['ident']), reverse=True)

    site_new_dir = setup_directory_structure(settings, base_dir, template_dir)
    generate_index_page(site_new_dir, base_html, section_html, medias)
    for media in medias:
        generate_video_page(base_dir, site_new_dir, base_html, showing_html,
                            media)
    site_dir = os.path.join(base_dir, 'site')
    publish_new_site(site_dir, site_new_dir)

    return 0

if __name__ == '__main__':
    sys.exit(main())
