# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import datetime
import itertools
import json
import logging
import multiprocessing
import os
import pprint
import re
import sys

from pelican.generators import ArticlesGenerator
from pelican.generators import PagesGenerator
from pelican.settings import DEFAULT_CONFIG
from pelican import signals
from pelican.utils import pelican_open

logger = logging.getLogger(__name__)

try:
    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageEnhance
    from PIL import ImageFont
    from PIL import ImageOps
except ImportError:
    logger.error('PIL/Pillow not found')

try:
    import piexif
except ImportError:
    ispiexif = False
    logger.warning('piexif not found! Cannot use exif manipulation features')
else:
    ispiexif = True
    logger.debug('piexif found.')


def initialized(pelican):
    p = os.path.expanduser('~/Pictures')

    DEFAULT_CONFIG.setdefault('PHOTO_LIBRARY', p)
    DEFAULT_CONFIG.setdefault('PHOTO_GALLERY', (1024, 768, 80))
    DEFAULT_CONFIG.setdefault('PHOTO_ARTICLE', (760, 506, 80))
    DEFAULT_CONFIG.setdefault('PHOTO_THUMB', (192, 144, 60))
    DEFAULT_CONFIG.setdefault('PHOTO_SQUARE_THUMB', False)
    DEFAULT_CONFIG.setdefault('PHOTO_GALLERY_TITLE', '')
    DEFAULT_CONFIG.setdefault('PHOTO_ALPHA_BACKGROUND_COLOR', (255, 255, 255))
    DEFAULT_CONFIG.setdefault('PHOTO_WATERMARK', False)
    DEFAULT_CONFIG.setdefault('PHOTO_WATERMARK_THUMB', False)
    DEFAULT_CONFIG.setdefault('PHOTO_WATERMARK_TEXT', DEFAULT_CONFIG['SITENAME'])
    DEFAULT_CONFIG.setdefault('PHOTO_WATERMARK_TEXT_COLOR', (255, 255, 255))
    DEFAULT_CONFIG.setdefault('PHOTO_WATERMARK_IMG', '')
    DEFAULT_CONFIG.setdefault('PHOTO_WATERMARK_IMG_SIZE', False)
    DEFAULT_CONFIG.setdefault('PHOTO_RESIZE_JOBS', 1)
    DEFAULT_CONFIG.setdefault('PHOTO_EXIF_KEEP', False)
    DEFAULT_CONFIG.setdefault('PHOTO_EXIF_REMOVE_GPS', False)
    DEFAULT_CONFIG.setdefault('PHOTO_EXIF_AUTOROTATE', True)
    DEFAULT_CONFIG.setdefault('PHOTO_EXIF_COPYRIGHT', False)
    DEFAULT_CONFIG.setdefault('PHOTO_EXIF_COPYRIGHT_AUTHOR', DEFAULT_CONFIG['SITENAME'])
    DEFAULT_CONFIG.setdefault('PHOTO_LIGHTBOX_GALLERY_ATTR', 'data-lightbox')
    DEFAULT_CONFIG.setdefault('PHOTO_LIGHTBOX_CAPTION_ATTR', 'data-title')
    DEFAULT_CONFIG.setdefault('PHOTO_EXCLUDE', [])
    DEFAULT_CONFIG.setdefault('PHOTO_EXCLUDEALL', False)
    DEFAULT_CONFIG.setdefault('PHOTO_SKIPTAG', '')

    DEFAULT_CONFIG['queue_resize'] = {}
    DEFAULT_CONFIG['created_galleries'] = {}
    DEFAULT_CONFIG['plugin_dir'] = os.path.dirname(os.path.realpath(__file__))

    if pelican:
        pelican.settings.setdefault('PHOTO_LIBRARY', p)
        pelican.settings.setdefault('PHOTO_GALLERY', (1024, 768, 80))
        pelican.settings.setdefault('PHOTO_ARTICLE', (760, 506, 80))
        pelican.settings.setdefault('PHOTO_THUMB', (192, 144, 60))
        pelican.settings.setdefault('PHOTO_SQUARE_THUMB', False)
        pelican.settings.setdefault('PHOTO_GALLERY_TITLE', '')
        pelican.settings.setdefault('PHOTO_ALPHA_BACKGROUND_COLOR', (255, 255, 255))
        pelican.settings.setdefault('PHOTO_WATERMARK', False)
        pelican.settings.setdefault('PHOTO_WATERMARK_THUMB', False)
        pelican.settings.setdefault('PHOTO_WATERMARK_TEXT', pelican.settings['SITENAME'])
        pelican.settings.setdefault('PHOTO_WATERMARK_TEXT_COLOR', (255, 255, 255))
        pelican.settings.setdefault('PHOTO_WATERMARK_IMG', '')
        pelican.settings.setdefault('PHOTO_WATERMARK_IMG_SIZE', False)
        pelican.settings.setdefault('PHOTO_RESIZE_JOBS', 1)
        pelican.settings.setdefault('PHOTO_EXIF_KEEP', False)
        pelican.settings.setdefault('PHOTO_EXIF_REMOVE_GPS', False)
        pelican.settings.setdefault('PHOTO_EXIF_AUTOROTATE', True)
        pelican.settings.setdefault('PHOTO_EXIF_COPYRIGHT', False)
        pelican.settings.setdefault('PHOTO_EXIF_COPYRIGHT_AUTHOR', pelican.settings['AUTHOR'])
        pelican.settings.setdefault('PHOTO_LIGHTBOX_GALLERY_ATTR', 'data-lightbox')
        pelican.settings.setdefault('PHOTO_LIGHTBOX_CAPTION_ATTR', 'data-title')
        # Need to change type, PHOTO_EXCLUDE must be iterable
        if pelican.settings['PHOTO_EXCLUDE'] is None:
            pelican.settings['PHOTO_EXCLUDE'] = []
        pelican.settings['PHOTO_EXCLUDEALL'] = pelican.settings['PHOTO_EXCLUDEALL'] == '1'

        if pelican.settings['PHOTO_SKIPTAG'] is None:
            pelican.settings.setdefault('PHOTO_SKIPTAG', '')

def read_notes(filename, msg=None):
    notes = {}
    try:
        with pelican_open(filename) as text:
            for line in text.splitlines():
                if line.startswith('#'):
                    continue
                m = line.split(':', 1)
                if len(m) > 1:
                    pic = m[0].strip()
                    note = m[1].strip()
                    if pic and note:
                        notes[pic] = note
                else:
                    notes[line] = ''
    except Exception as e:
        if msg:
            logger.info('{} at file {}'.format(msg, filename))
        logger.debug('read_notes issue: {} at file {}. Debug message:{}'.format(msg, filename, e))
    return notes


def enqueue_resize(orig, resized, spec=(640, 480, 80)):
    if resized not in DEFAULT_CONFIG['queue_resize']:
        DEFAULT_CONFIG['queue_resize'][resized] = (orig, spec)
    elif DEFAULT_CONFIG['queue_resize'][resized] != (orig, spec):
        error_msg = 'photos: resize conflict for {}, {}-{} is not {}-{}'
        logger.error(error_msg.format(resized, DEFAULT_CONFIG['queue_resize'][resized][0],
                                      DEFAULT_CONFIG['queue_resize'][resized][1], orig, spec))


def isalpha(img):
    return True if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info) else False


def remove_alpha(img, bg_color):
    background = Image.new("RGB", img.size, bg_color)
    background.paste(img, mask=img.split()[3])  # 3 is the alpha channel
    return background


def ReduceOpacity(im, opacity):
    """Reduces Opacity.

    Returns an image with reduced opacity.
    Taken from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/362879
    """
    assert opacity >= 0 and opacity <= 1
    if isalpha(im):
        im = im.copy()
    else:
        im = im.convert('RGBA')

    alpha = im.split()[3]
    alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
    im.putalpha(alpha)
    return im


def watermark_photo(image, settings):
    margin = [10, 10]
    opacity = 0.6

    watermark_layer = Image.new("RGBA", image.size, (0, 0, 0, 0))
    draw_watermark = ImageDraw.Draw(watermark_layer)
    text_reducer = 32
    image_reducer = 8
    text_size = [0, 0]
    mark_size = [0, 0]
    text_position = [0, 0]

    if settings['PHOTO_WATERMARK_TEXT']:
        font_name = 'SourceCodePro-Bold.otf'
        default_font = os.path.join(DEFAULT_CONFIG['plugin_dir'], font_name)
        font = ImageFont.FreeTypeFont(default_font, watermark_layer.size[0] // text_reducer)
        text_size = draw_watermark.textsize(settings['PHOTO_WATERMARK_TEXT'], font)
        text_position = [image.size[i] - text_size[i] - margin[i] for i in [0, 1]]
        draw_watermark.text(text_position, settings['PHOTO_WATERMARK_TEXT'], settings['PHOTO_WATERMARK_TEXT_COLOR'], font=font)

    if settings['PHOTO_WATERMARK_IMG']:
        mark_image = Image.open(settings['PHOTO_WATERMARK_IMG'])
        mark_image_size = [watermark_layer.size[0] // image_reducer for size in mark_size]
        mark_image_size = settings['PHOTO_WATERMARK_IMG_SIZE'] if settings['PHOTO_WATERMARK_IMG_SIZE'] else mark_image_size
        mark_image.thumbnail(mark_image_size, Image.ANTIALIAS)
        mark_position = [watermark_layer.size[i] - mark_image.size[i] - margin[i] for i in [0, 1]]
        mark_position = tuple([mark_position[0] - (text_size[0] // 2) + (mark_image_size[0] // 2), mark_position[1] - text_size[1]])

        if not isalpha(mark_image):
            mark_image = mark_image.convert('RGBA')

        watermark_layer.paste(mark_image, mark_position, mark_image)

    watermark_layer = ReduceOpacity(watermark_layer, opacity)
    image.paste(watermark_layer, (0, 0), watermark_layer)

    return image


def rotate_image(img, exif_dict):
    if "exif" in img.info and piexif.ImageIFD.Orientation in exif_dict["0th"]:
        orientation = exif_dict["0th"].pop(piexif.ImageIFD.Orientation)
        if orientation == 2:
            img = img.transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 3:
            img = img.rotate(180)
        elif orientation == 4:
            img = img.rotate(180).transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 5:
            img = img.rotate(-90).transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 6:
            img = img.rotate(-90, expand=True)
        elif orientation == 7:
            img = img.rotate(90).transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 8:
            img = img.rotate(90)

    return (img, exif_dict)


def build_license(license, author):
    year = datetime.datetime.now().year
    license_file = os.path.join(DEFAULT_CONFIG['plugin_dir'], 'licenses.json')

    with open(license_file) as data_file:
        licenses = json.load(data_file)

    if any(license in k for k in licenses):
        return licenses[license]['Text'].format(Author=author, Year=year, URL=licenses[license]['URL'])
    else:
        return 'Copyright {Year} {Author}, All Rights Reserved'.format(Author=author, Year=year)


def manipulate_exif(img, settings):
    try:
        exif = piexif.load(img.info['exif'])
    except Exception:
        logger.debug('EXIF information not found')
        exif = {}

    if settings['PHOTO_EXIF_AUTOROTATE']:
        img, exif = rotate_image(img, exif)

    if settings['PHOTO_EXIF_REMOVE_GPS']:
        exif.pop('GPS')

    if settings['PHOTO_EXIF_COPYRIGHT']:

        # We want to be minimally destructive to any preset exif author or copyright information.
        # If there is copyright or author information prefer that over everything else.
        if not exif['0th'].get(piexif.ImageIFD.Artist):
            exif['0th'][piexif.ImageIFD.Artist] = settings['PHOTO_EXIF_COPYRIGHT_AUTHOR']
            author = settings['PHOTO_EXIF_COPYRIGHT_AUTHOR']

        if not exif['0th'].get(piexif.ImageIFD.Copyright):
            license = build_license(settings['PHOTO_EXIF_COPYRIGHT'], author)
            exif['0th'][piexif.ImageIFD.Copyright] = license

    return (img, piexif.dump(exif))


# Define a global lock as 'apply_async' doesn't support sharing primitives
GLock = multiprocessing.Lock()

def resize_worker(orig, resized, spec, settings):
    logger.info('photos: make photo {} -> {}'.format(orig, resized))
    im = Image.open(orig)

    if ispiexif and settings['PHOTO_EXIF_KEEP'] and im.format == 'JPEG':  # Only works with JPEG exif for sure.
        try:
            im, exif_copy = manipulate_exif(im, settings)
        except:
            logger.info('photos: no EXIF or EXIF error in {}'.format(orig))
            exif_copy = b''
    else:
        exif_copy = b''

    icc_profile = im.info.get("icc_profile", None)

    if settings['PHOTO_SQUARE_THUMB'] and spec == settings['PHOTO_THUMB']:
        im = ImageOps.fit(im, (spec[0], spec[1]), Image.ANTIALIAS)

    im.thumbnail((spec[0], spec[1]), Image.ANTIALIAS)
    directory = os.path.split(resized)[0]

    if isalpha(im):
        im = remove_alpha(im, settings['PHOTO_ALPHA_BACKGROUND_COLOR'])

    GLock.acquire()
    if not os.path.exists(directory):
        try:
            os.makedirs(directory)
        except Exception:
            logger.exception('Could not create {}'.format(directory))
    else:
        if not settings['PHOTO_SKIPTAG']:
            logger.debug('Directory already exists at {}'.format(os.path.split(resized)[0]))
    GLock.release()

    if settings['PHOTO_WATERMARK']:
        isthumb = True if spec == settings['PHOTO_THUMB'] else False
        if not isthumb or (isthumb and settings['PHOTO_WATERMARK_THUMB']):
            im = watermark_photo(im, settings)

    try:
        im.save(resized, 'JPEG', quality=spec[2], icc_profile=icc_profile, exif=exif_copy)

        if settings['PHOTO_SKIPTAG']:
            if not resized.endswith('.tmb.jpg'):
                output_path = os.path.realpath(settings['OUTPUT_PATH'])
                output_photos_path = os.path.join(output_path, 'photos')
                cleaner_sh = os.path.join(output_photos_path, 'clean_skiptag.sh')
                resized_relpath = os.path.relpath(resized, output_photos_path)
                original_relpath = os.path.join(os.path.dirname(resized_relpath),
                                                os.path.basename(orig))
                try:
                    GLock.acquire()
                    with open(cleaner_sh, "a") as bash_script:
                        bash_line = "[ ! -f '{}' ] || rm -f '{}'"
                        print(bash_line.format(resized_relpath, original_relpath),
                              file=bash_script)
                    GLock.release()
                except Exception as e:
                    except_msg = 'photos: could not open file {}'
                    logger.exception(except_msg.format(cleaner_sh))
                    GLock.release()

    except Exception as e:
         logger.exception('photos: could not save image {}'.format(resized))


def resize_photos(generator, writer):
    if generator.settings['PHOTO_EXCLUDEALL']:
        logger.warning('photos: Skip all galleries')
        return

    if generator.settings['PHOTO_RESIZE_JOBS'] == -1:
        debug = True
        generator.settings['PHOTO_RESIZE_JOBS'] = 1
    else:
        debug = False

    pool = multiprocessing.Pool(generator.settings['PHOTO_RESIZE_JOBS'])
    logger.debug('Debug Status: {}'.format(debug))
    for resized, what in DEFAULT_CONFIG['queue_resize'].items():
        resized = os.path.join(generator.output_path, resized)
        abs_path = os.path.split(resized)[0]
        basename = os.path.basename(abs_path)

        if basename in generator.settings['PHOTO_EXCLUDE']:
            logger.warning('photos: skip gallery: {}'.format(basename))
            continue

        orig, spec = what
        if (not os.path.isfile(resized) or os.path.getmtime(orig) > os.path.getmtime(resized)):
            if debug:
                resize_worker(orig, resized, spec, generator.settings)
            else:
                pool.apply_async(resize_worker, (orig, resized, spec, generator.settings))

    pool.close()
    pool.join()


def detect_content(content):
    hrefs = None

    def replacer(m):
        what = m.group('what')
        value = m.group('value')
        tag = m.group('tag')
        output = m.group(0)

        if what in ('photo', 'lightbox'):
            if value.startswith('/'):
                value = value[1:]

            path = os.path.join(
                os.path.expanduser(settings['PHOTO_LIBRARY']),
                value
            )

            if os.path.isfile(path):
                original_filename = os.path.basename(path)
                if original_filename.endswith('.tmb.jpg'):
                    return output

                do_enqueue = True
                do_rename = False
                if settings['PHOTO_SKIPTAG']:
                    if original_filename.startswith(settings['PHOTO_SKIPTAG']):
                        debug_msg = 'photos: flagged to skip: {}'
                        logger.debug(debug_msg.format(original_filename))
                        do_enqueue = False
                    else:
                        do_rename = True

                photo_prefix = os.path.splitext(value)[0].lower()
                if do_rename:
                    photo_prefix = settings['PHOTO_SKIPTAG'] + photo_prefix

                if what == 'photo':
                    photo_article = photo_prefix + '.art.jpg'
                    if do_enqueue:
                        enqueue_resize(
                            path,
                            os.path.join('photos', photo_article),
                            settings['PHOTO_ARTICLE']
                        )

                    output = ''.join((
                        '<',
                        m.group('tag'),
                        m.group('attrs_before'),
                        m.group('src'),
                        '=',
                        m.group('quote'),
                        os.path.join(settings['SITEURL'], 'photos', photo_article),
                        m.group('quote'),
                        m.group('attrs_after'),
                    ))

                elif what == 'lightbox' and tag == 'img':
                    photo_gallery = photo_prefix + '.jpg'
                    if do_enqueue:
                        enqueue_resize(
                            path,
                            os.path.join('photos', photo_gallery),
                            settings['PHOTO_GALLERY']
                        )

                        photo_thumb = photo_prefix + '.tbm.jpg'
                        enqueue_resize(
                            path,
                            os.path.join('photos', photo_thumb),
                            settings['PHOTO_THUMB']
                        )

                    lightbox_attr_list = ['']

                    gallery_name = value.split('/')[0]
                    lightbox_attr_list.append('{}="{}"'.format(
                        settings['PHOTO_LIGHTBOX_GALLERY_ATTR'],
                        gallery_name
                    ))

                    captions = read_notes(
                        os.path.join(os.path.dirname(path), 'captions.txt'),
                        msg = 'photos: No captions for gallery'
                    )
                    caption = captions.get(os.path.basename(path)) if captions else None
                    if caption:
                        lightbox_attr_list.append('{}="{}"'.format(
                            settings['PHOTO_LIGHTBOX_CAPTION_ATTR'],
                            caption
                        ))

                    lightbox_attrs = ' '.join(lightbox_attr_list)

                    output = ''.join((
                        '<a href=',
                        m.group('quote'),
                        os.path.join(settings['SITEURL'], 'photos', photo_gallery),
                        m.group('quote'),
                        lightbox_attrs,
                        '><img',
                        m.group('attrs_before'),
                        'src=',
                        m.group('quote'),
                        os.path.join(settings['SITEURL'], 'photos', photo_thumb),
                        m.group('quote'),
                        m.group('attrs_after'),
                        '</a>'
                    ))

            else:
                logger.error('photos: No photo %s', path)

        return output

    if hrefs is None:
        regex = r"""
            <\s*
            (?P<tag>[^\s\>]+)  # detect the tag
            (?P<attrs_before>[^\>]*)
            (?P<src>href|src)  # match tag with src and href attr
            \s*=
            (?P<quote>["\'])  # require value to be quoted
            (?P<path>{0}(?P<value>.*?))  # the url value
            (?P=quote)
            (?P<attrs_after>[^\>]*>)
        """.format(
            content.settings['INTRASITE_LINK_REGEX']
        )
        hrefs = re.compile(regex, re.X)

    if content._content and ('{photo}' in content._content or '{lightbox}' in content._content):
        settings = content.settings
        content._content = hrefs.sub(replacer, content._content)


def galleries_string_decompose(gallery_string):
    splitter_regex = re.compile(r'[\s,]*?({photo}|{filename})')
    title_regex = re.compile(r'{(.+)}')
    galleries = map(unicode.strip if sys.version_info.major == 2 else str.strip, filter(None, splitter_regex.split(gallery_string)))
    galleries = [gallery[1:] if gallery.startswith('/') else gallery for gallery in galleries]
    if len(galleries) % 2 == 0 and ' ' not in galleries:
        galleries = zip(zip(['type'] * len(galleries[0::2]), galleries[0::2]), zip(['location'] * len(galleries[0::2]), galleries[1::2]))
        galleries = [dict(gallery) for gallery in galleries]
        for gallery in galleries:
            title = re.search(title_regex, gallery['location'])
            if title:
                gallery['title'] = title.group(1)
                gallery['location'] = re.sub(title_regex, '', gallery['location']).strip()
            else:
                gallery['title'] = DEFAULT_CONFIG['PHOTO_GALLERY_TITLE']
        return galleries
    else:
        logger.error('Unexpected gallery location format! \n{}'.format(pprint.pformat(galleries)))


def process_gallery(generator, content, location):
    content.photo_gallery = []

    galleries = galleries_string_decompose(location)

    for gallery in galleries:

        if gallery['location'] in DEFAULT_CONFIG['created_galleries']:
            content.photo_gallery.append((gallery['location'], DEFAULT_CONFIG['created_galleries'][gallery]))
            continue

        if gallery['type'] == '{photo}':
            dir_gallery = os.path.join(os.path.expanduser(generator.settings['PHOTO_LIBRARY']), gallery['location'])
            rel_gallery = gallery['location']
        elif gallery['type'] == '{filename}':
            base_path = os.path.join(generator.path, content.relative_dir)
            dir_gallery = os.path.join(base_path, gallery['location'])
            rel_gallery = os.path.join(content.relative_dir, gallery['location'])

        if os.path.isdir(dir_gallery):
            logger.info('photos: Gallery detected: {}'.format(rel_gallery))
            dir_photo = os.path.join('photos', rel_gallery.lower())
            dir_thumb = os.path.join('photos', rel_gallery.lower())

            try:
                exifs = read_notes(os.path.join(dir_gallery, 'exif.txt'),
                                   msg='photos: No EXIF for gallery')
                captions = read_notes(os.path.join(dir_gallery, 'captions.txt'),
                                      msg='photos: No captions for gallery')
                blacklist = read_notes(os.path.join(dir_gallery, 'blacklist.txt'),
                                       msg='photos: No blacklist for gallery')
            except Exception as e:
                logger.debug('photos: exception {}'.format(pprint.pformat(e)))

            content_gallery = []
            title = gallery['title']

            for pic in sorted(os.listdir(dir_gallery)):
                if pic.startswith('.'):
                    continue
                if pic.endswith('.txt'):
                    continue
                if pic.endswith('.tmb.jpg'):
                    continue
                if pic in blacklist:
                    continue

                do_enqueue = True
                do_rename = False
                if generator.settings['PHOTO_SKIPTAG']:
                    if pic.startswith(generator.settings['PHOTO_SKIPTAG']):
                        debug_msg = 'photos: flagged to skip: {}'
                        logger.debug(debug_msg.format(pic))
                        do_enqueue = False
                    else:
                        do_rename = True

                photo = os.path.splitext(pic)[0].lower() + '.jpg'
                thumb = os.path.splitext(pic)[0].lower() + '.tmb.jpg'

                if do_rename:
                    photo = generator.settings['PHOTO_SKIPTAG'] + photo
                    thumb = generator.settings['PHOTO_SKIPTAG'] + thumb

                if do_enqueue:
                    enqueue_resize(
                        os.path.join(dir_gallery, pic),
                        os.path.join(dir_photo, photo),
                        generator.settings['PHOTO_GALLERY'])
                    enqueue_resize(
                        os.path.join(dir_gallery, pic),
                        os.path.join(dir_thumb, thumb),
                        generator.settings['PHOTO_THUMB'])

                content_gallery.append((
                    pic,
                    os.path.join(dir_photo, photo),
                    os.path.join(dir_thumb, thumb),
                    exifs.get(pic, ''),
                    captions.get(pic, '')))

            content.photo_gallery.append((title, content_gallery))
            logger.debug('Gallery Data: {}'.format(pprint.pformat(content.photo_gallery)))
            DEFAULT_CONFIG['created_galleries']['gallery'] = content_gallery
        else:
            logger.error('photos: Gallery does not exist: {} at {}'.format(gallery['location'], dir_gallery))


def detect_gallery(generator, content):
    if 'photo-gallery' in content.metadata:
        gallery = content.metadata.get('photo-gallery')
        if gallery.startswith('{photo}') or gallery.startswith('{filename}'):
            process_gallery(generator, content, gallery)
        elif gallery:
            logger.error('photos: Gallery tag not recognized: {}'.format(gallery))


def image_clipper(x):
    return x[8:] if x[8] == '/' else x[7:]


def file_clipper(x):
    return x[11:] if x[10] == '/' else x[10:]


def process_image(generator, content, image):
    if image.startswith('{photo}'):
        path = os.path.join(os.path.expanduser(generator.settings['PHOTO_LIBRARY']), image_clipper(image))
        image = image_clipper(image)
    elif image.startswith('{filename}'):
        path = os.path.join(generator.path, content.relative_dir, file_clipper(image))
        image = file_clipper(image)

    if os.path.isfile(path):
        original_filename = os.path.basename(path)
        if original_filename.endswith('.tmb.jpg'):
            return

        do_enqueue = True
        do_rename = False
        if generator.settings['PHOTO_SKIPTAG']:
            if original_filename.startswith(generator.settings['PHOTO_SKIPTAG']):
                debug_msg = 'photos: flagged to skip: {}'
                logger.debug(debug_msg.format(original_filename))
                do_enqueue = False
            else:
                do_rename = True

        photo = os.path.splitext(image)[0].lower() + '.art.jpg'
        thumb = os.path.splitext(image)[0].lower() + '.tmb.jpg'

        if do_rename:
            photo = generator.settings['PHOTO_SKIPTAG'] + photo
            thumb = generator.settings['PHOTO_SKIPTAG'] + thumb

        if do_enqueue:
            enqueue_resize(
                path,
                os.path.join('photos', photo),
                generator.settings['PHOTO_ARTICLE'])
            enqueue_resize(
                path,
                os.path.join('photos', thumb),
                generator.settings['PHOTO_THUMB'])

        content.photo_image = (
            os.path.basename(image).lower(),
            os.path.join('photos', photo),
            os.path.join('photos', thumb))
    else:
        logger.error('photo: No photo for {} at {}'.format(content.source_path, path))


def detect_image(generator, content):
    image = content.metadata.get('image', None)
    if image:
        if image.startswith('{photo}') or image.startswith('{filename}'):
            process_image(generator, content, image)
        else:
            logger.error('photos: Image tag not recognized: {}'.format(image))


def detect_images_and_galleries(generators):
    """Runs generator on both pages and articles."""
    for generator in generators:
        if isinstance(generator, ArticlesGenerator):
            for article in itertools.chain(generator.articles, generator.translations, generator.drafts):
                detect_image(generator, article)
                detect_gallery(generator, article)
        elif isinstance(generator, PagesGenerator):
            for page in itertools.chain(generator.pages, generator.translations, generator.hidden_pages):
                detect_image(generator, page)
                detect_gallery(generator, page)


def register():
    """Uses the new style of registration based on GitHub Pelican issue #314."""
    signals.initialized.connect(initialized)
    try:
        signals.content_object_init.connect(detect_content)
        signals.all_generators_finalized.connect(detect_images_and_galleries)
        signals.article_writer_finalized.connect(resize_photos)
    except Exception as e:
        logger.exception('Plugin failed to execute: {}'.format(pprint.pformat(e)))
