#!/usr/bin/env python
'''
Icon generator
==============

This tool will help you to generate all the icons wanted for Google Play Store,
App Store, Amazon store.
'''

import sys
from PIL import Image
from os.path import exists, join, realpath, basename, dirname
from os import makedirs
from argparse import ArgumentParser


class Converter(object):

    converters = {
        'appstore': {
            'directory_name': 'ios',
            'sizes': [
                ('App store high resolution', '{}-appstore-1024.png', 1024),
                ('App store normal resolution', '{}-appstore-512.png', 512),
                # iOS 7
                ('iPhone (iOS 7)', '{}-60.png', 120),
                ('iPhone @2 (iOS 7)', '{}-60@2x.png', 120),
                ('iPad (iOS 7)', '{}-76.png', 76),
                ('iPad @2 (iOS 7)', '{}-60@2x.png', 152),
                # iOS 6.1 and earlier
                ('iPhone (iOS >= 6.1)', '{}-57.png', 57),
                ('iPhone @2 (iOS >= 6.1)', '{}-57@2x.png', 114),
                ('iPad (iOS >= 6.1)', '{}-72.png', 72),
                ('iPad @2 (iOS >= 6.1)', '{}-72@2x.png', 114),
                # iTunes artwork (ad-hoc)
                ('iTunes Artwork (ad-hoc)', 'iTunesArtwork', 512),
                ('iTunes Artwork @2 (ad-hoc)', 'iTunesArtwork@2x', 1024),
            ]},
        'playstore': {
            'directory_name': 'android',
            'sizes': [
                ('Google Play icon', '{}-googleplay-512.png', 512),
                ('Launcher icon MDPI', '{}-48.png', 48),
                ('Launcher icon HDPI', '{}-72.png', 72),
                ('Launcher icon XHDPI', '{}-96.png', 96),
                ('Launcher icon XXHDPI', '{}-144.png', 48),
                ('Launcher icon XXXHDPI', '{}-192.png', 192),
            ]},
        'amazonstore': {
            'directory_name': 'amazon',
            'sizes': [
                ('Small icon', '{}-114.png', 114),
                ('Large icon', '{}-512.png', 512),
            ]}}

    def run(self):
        parser = ArgumentParser(
                description='Generate icons for various stores')
        parser.add_argument('--dir', type=str, default=None,
                help=('Output directory to generate all the icons,'
                      'defaults to the directory of the source icon'))
        parser.add_argument('--force', type=bool, default=False,
                help=('Generate all icons even if the source is not perfect.'))
        parser.add_argument('icon', type=str,
                help='Base icon (must be 1024x1024 or 512x512)')

        args = parser.parse_args()
        if not exists(args.icon):
            print('Error: No such icon file')
            sys.exit(1)

        # ensure the destination directory will be set
        if args.dir is None:
            args.dir = dirname(args.icon)

        # read the source image, and do some quality checks
        base_fn = basename(args.icon).rsplit('.', 1)[0]
        source = Image.open(args.icon)
        self.ensure_quality(source, args.force)

        for directory_name, sizeinfo in self.iterate():
            description, pattern_fn, size = sizeinfo
            print('Generate {}: {}x{}'.format(description, size, size))
            dest_dir = realpath(join(args.dir, directory_name))
            if not exists(dest_dir):
                makedirs(dest_dir)
            icon_fn = join(dest_dir, pattern_fn.format('Icon'))
            self.convert_to(source, icon_fn, size)

    def convert_to(self, source, icon_fn, size):
        dest = source.resize((size, size))
        dest.save(icon_fn, 'png')

    def ensure_quality(self, image, force=False):
        messages = []
        w, h = image.size
        if w != h:
            messages.append('Width and height should be the same')
        if w not in (512, 1024):
            messages.append(
                'Source image is recommended to be 1024 (512 minimum)')
        if not messages:
            return

        print('Quality check failed')
        for message in messages:
            print('- {}'.format(message))
        if not force:
            sys.exit(1)

    def iterate(self):
        for store, infos in Converter.converters.items():
            for size in infos['sizes']:
                yield infos['directory_name'], size


if __name__ == '__main__':
    Converter().run()
