import json
import os
from distutils.core import setup
from os.path import abspath, dirname, exists, getsize, join, relpath, splitext

from setuptools import Command

here = abspath(dirname(__file__))

about = {}
# Get meta-data from __version__.py
with open(join(here, 'mimesis', '__version__.py')) as f:
    exec(f.read(), about)


class BaseCommand(Command):
    description = ''
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        pass


class Minimizer(BaseCommand):
    """Minify content of all json file for all locales.
    """

    def initialize_options(self):
        """Find all files of all locales.
        """

        self.paths = []
        self.separators = (',', ':')
        self.data_dir = join(here, 'mimesis', 'data')
        self.before_total = 0
        self.after_total = 0

        for root, _, files in os.walk(self.data_dir):
            for file in sorted(files):
                if splitext(file)[1] == '.json':
                    self.paths.append(join(
                        relpath(root, self.data_dir), file))

    @staticmethod
    def size_of(num):
        for unit in ['B', 'KB', 'MB']:
            if abs(num) < 1024.0:
                return "%3.1f%s" % (num, unit)
            num = num / 1024.0
        return "%.1f" % num

    def minify(self, file_path):
        size_before = getsize(file_path)
        self.before_total += size_before
        size_before = self.size_of(size_before)

        with open(file_path, 'r', 1) as f:
            json_text = json.loads(f.read())
            minimized = json.dumps(
                json_text, separators=self.separators, ensure_ascii=False)

        if len(file_path) > 0:
            output_path = abspath(file_path)
            abs_path = abspath(dirname(output_path))

            if not exists(abs_path):
                os.makedirs(abs_path)

            with open(output_path, 'w+', 1) as f:
                f.write(minimized)

        size_after = getsize(file_path)
        self.after_total += size_after
        size_after = self.size_of(size_after)

        json_file = '/'.join(file_path.split('/')[-2:])

        template = "\033[34m{}\033[0m : " \
                   "\033[92mminimized\033[0m : " \
                   "\033[33m{}\033[0m -> \033[92m{}\033[0m"

        print(template.format(json_file,
                              size_before, size_after))

    def run(self):
        """Start json minimizer and exit when all json
        files was minimized.
        """
        for rel_path in sorted(self.paths):
            file_path = join(self.data_dir, rel_path)
            self.minify(file_path)

        after = self.size_of(self.after_total)
        before = self.size_of(self.before_total)
        saved = self.size_of(self.before_total - self.after_total)

        template = '\nTotal: ' \
                   '\033[92m{}\033[0m -> \033[92m{}\033[0m. ' \
                   'Compressed: \033[92m{}\033[0m\n'

        print(template.format(before, after, saved))


with open('README.rst', 'r', encoding='utf-8') as f:
    readme = f.read()


setup(
    name=about['__title__'],
    version=about['__version__'],
    description=about['__description__'],
    long_description=readme,
    author=about['__author__'],
    author_email=about['__author_email__'],
    url=about['__url__'],
    license=about['__license__'],
    packages=[
        'mimesis',
        'mimesis.data',
        'mimesis.data.int',
        'mimesis.builtins',
        'mimesis.providers',
    ],
    keywords=[
        'fake',
        'mock',
        'data',
        'populate',
        'database',
        'testing',
        'generate',
        'mimesis',
        'dummy',
    ],
    package_data={
        'mimesis': [
            'data/*/*',
        ],
    },
    exclude_package_data={
        'mimesis': [
            # It's for development.
            'data/locale_template/*'
        ],
    },
    data_files=[
        ('', ['LICENSE']),
    ],
    classifiers=[
        'License :: OSI Approved :: MIT License',
        'Intended Audience :: Developers',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: Implementation :: CPython',
        'Operating System :: OS Independent',
        'Topic :: Software Development',
        'Topic :: Software Development :: Testing',
    ],
    cmdclass={
        'minify': Minimizer,
    },
)
