import configparser
import math
import re
import urllib
from pathlib import Path
from PIL import Image

def get_images(image_directory, thumbnail_directory, thumbnail_size):
    thumbnail_directory = Path(thumbnail_directory)

    for file in [file for file in thumbnail_directory.glob('*')]:
        file.unlink()

    thumbnail_directory.mkdir(mode=0o755, exist_ok=True)

    files = [file for file in Path(image_directory).glob('*')]

    images = []

    for file in files:
        thumbnail_name = Path(thumbnail_directory, file.stem + '.jpg')

        image = Image.open(file)
        image.thumbnail(thumbnail_size)

        top_left = (0, 0)

        if image.width < thumbnail_size[0]:
            top_left = (math.floor(abs(image.width - thumbnail_size[0]) / 2), top_left[1])

        if image.height < thumbnail_size[1]:
            top_left = (top_left[0], math.floor(abs(image.height - thumbnail_size[1]) / 2))

        final_image = Image.new('RGB', thumbnail_size, (0, 0, 0))
        final_image.paste(image, top_left)
        final_image.save(thumbnail_name, 'jpeg')

        if '_' in file.stem:
            description = file.stem.split('_', maxsplit=1)[1]
        else:
            description = file.stem

        images.append({
                'path': str(file),
                'thumbnail': thumbnail_name,
                'description': description,
                'stem': file.stem
            })

    def get_image_file_number(image):
        if re.match(r'^(\d+)', image['stem']) is not None:
            return int(re.split(r'^(\d+)', image['stem'])[1])
        else:
            return 999

    images = sorted(images, key=get_image_file_number)

    return images

def write_html(file, images, page_title, thumbnail_size):
    file.write(f'''\
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>{page_title}</title>
  <link rel="stylesheet" type="text/css" href="album.css">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
  <h1>{page_title}</h1>
  <div id="album">
    \
''')

    # write thumbnails
    for image, idx in zip(images, range(1, len(images) + 1)):
        thumbnail_path = urllib.parse.quote(str(image['thumbnail']).replace('\\', '/'))

        file.write(f'''\
<p id="thumbnail-{idx}" class="thumbnail"><img src="{thumbnail_path}" alt="{image['description']}" width="{thumbnail_size[0]}" height="{thumbnail_size[1]}"></p>\
''')

    file.write(f'''\

    <div id="large-view">
      <p id="instructions" class="image">Hover over an image</p>
''')

    # write images
    for image, idx in zip(images, range(1, len(images) + 1)):
        image_path = urllib.parse.quote(str(image['path']).replace('\\', '/'))

        file.write(f'''\
      <p id="image-{idx}" class="image"><img src="{image_path}" alt="{image['description']}"><br>{image['description']}</p>
''')

    file.write(f'''\
    </div>
  </div>
</body>
</html>
''')

def write_css(file, images):
    file.write('''\
@media print {
    body {
        font-family: sans-serif;
    }

    .thumbnail {
        display: none;
    }

    #instructions {
        display: none;
    }

    .image img {
        max-width: 100%;
        margin-bottom: 1em;
    }
}

@media
    screen and (max-width: 768px),

    /* Tablets and smartphones */
    screen and (hover: none)
{
    body {
        background: #333;
        color: #eee;
        font-family: sans-serif;
        margin: 1em;
        padding: 0;
    }

    h1 {
        margin-top: 0;
    }

    .thumbnail {
        display: none;
    }

    #instructions {
        display: none;
    }

    .image:nth-child(2) img {
        margin-top: 0;
    }

    .image img {
        max-width: calc(100vw - 3em);
    }
}

@media
    screen and (min-width: 769px) and (hover: hover),

    /* IE10 and IE11 (they don't support (hover: hover) */
    screen and (min-width: 769px) and (-ms-high-contrast: none),
    screen and (min-width: 769px) and (-ms-high-contrast: active)
{
    body {
        background: #333;
        color: #eee;
        font-family: sans-serif;
        margin: 2em 60% 2em 4em;
        padding: 0;
    }

    .album {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
    }

    .thumbnail {
        display: inline-block;;
        margin: 0 .5em .2em 0;
    }

    .image {
        background: #333;
        display: none;
        position: fixed;
        top: 2em;
        left: 40%;
        text-align: center;
        height: 90vh;
        width: calc(60% - 4em);
    }

    .image img {
        display: block;
        max-height: 92%;
        max-width: 100%;
        margin: 0 auto;
    }

    #instructions {
        display: block;
        top: 4em;
    }

''')

    if len(images) > 0:
        for idx in range(1, len(images) + 1):
            file.write(f'''\
    #thumbnail-{idx}:hover ~ #large-view #image-{idx}\
''')

            if idx < len(images):
                file.write('''\
,
''')

        file.write('''\
 {
        display: block;
    }
''')

    file.write('''\
}
''')

def main():
    config = configparser.ConfigParser()
    config.read('./config')

    image_directory = config['settings']['image_directory']
    output_css = config['settings']['output_css']
    output_html = config['settings']['output_html']
    page_title = config['settings']['page_title']
    thumbnail_directory = config['settings']['thumbnail_directory']
    thumbnail_width = int(config['settings']['thumbnail_width'])
    thumbnail_height = int(config['settings']['thumbnail_height'])
    thumbnail_size = (thumbnail_width, thumbnail_height)

    out_html = open(output_html, 'w')
    out_css = open(output_css, 'w')

    images = get_images(image_directory, thumbnail_directory, thumbnail_size)

    write_html(out_html, images, page_title, thumbnail_size)
    write_css(out_css, images)

    out_html.close()
    out_css.close()

if __name__ == '__main__':
    main()

[(9, 'pathlib.Path', 'Path', False, 'from pathlib import Path\n'), (234, 'configparser.ConfigParser', 'configparser.ConfigParser', False, 'import configparser\n'), (21, 'pathlib.Path', 'Path', False, 'from pathlib import Path\n'), (23, 'PIL.Image.open', 'Image.open', False, 'from PIL import Image\n'), (34, 'PIL.Image.new', 'Image.new', False, 'from PIL import Image\n'), (51, 're.match', 're.match', False, 'import re\n'), (16, 'pathlib.Path', 'Path', False, 'from pathlib import Path\n'), (52, 're.split', 're.split', False, 'import re\n')]