# !/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Defines unit tests for :mod:`colour_hdri.process.adobe_dng` module.
"""

from __future__ import division, unicode_literals

import numpy as np
import os
import platform
import shutil
import tempfile
import unittest
import zipfile

from colour import read_image

from colour_hdri import TESTS_RESOURCES_DIRECTORY
from colour_hdri.process import (convert_raw_files_to_dng_files,
                                 convert_dng_files_to_intermediate_files,
                                 read_dng_files_exif_tags)
from colour_hdri.utilities import filter_files

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers'
__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-developers@colour-science.org'
__status__ = 'Production'

__all__ = [
    'FROBISHER_001_DIRECTORY', 'PROCESS_DIRECTORY', 'RAW_IMAGES',
    'TestConvertRawFilesToDngFiles', 'TestConvertDngFilesToIntermediateFiles'
]

FROBISHER_001_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY,
                                       'frobisher_001')

PROCESS_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY, 'colour_hdri',
                                 'process')

RAW_IMAGES = filter_files(FROBISHER_001_DIRECTORY, ('CR2', ))


class TestConvertRawFilesToDngFiles(unittest.TestCase):
    """
    Defines :func:`colour_hdri.process.adobe_dng.\
convert_raw_files_to_dng_files` definition unit tests methods.
    """

    def setUp(self):
        """
        Initialises common tests attributes.
        """

        self._temporary_directory = tempfile.mkdtemp()

    def tearDown(self):
        """
        After tests actions.
        """

        shutil.rmtree(self._temporary_directory)

    def test_convert_raw_files_to_dng_files(self):
        """
        Tests :func:`colour_hdri.process.adobe_dng.\
convert_raw_files_to_dng_files` definition.
        """

        if platform.system() not in ('Windows', 'Microsoft'):
            # *Adobe DNG Converter* is not available on *Linux*, and is not
            # reproducible on *macOS* thus we skip this unit test.
            return

        reference_dng_files = sorted(
            filter_files(PROCESS_DIRECTORY, ('dng', )))
        test_dng_files = sorted(
            convert_raw_files_to_dng_files(RAW_IMAGES,
                                           self._temporary_directory))

        for test_dng_file, reference_dng_file in zip(test_dng_files,
                                                     reference_dng_files):
            np.testing.assert_almost_equal(
                read_image(str(test_dng_file)),
                read_image(str(reference_dng_file)),
                decimal=7)


class TestConvertDngFilesToIntermediateFiles(unittest.TestCase):
    """
    Defines :func:`colour_hdri.process.adobe_dng.\
convert_dng_files_to_intermediate_files` definition unit tests methods.
    """

    def setUp(self):
        """
        Initialises common tests attributes.
        """

        self._temporary_directory = tempfile.mkdtemp()

    def tearDown(self):
        """
        After tests actions.
        """

        shutil.rmtree(self._temporary_directory)

    def test_convert_dng_files_to_intermediate_files(self):
        """
        Tests :func:`colour_hdri.process.adobe_dng.\
convert_dng_files_to_intermediate_files` definition.
        """

        reference_dng_files = sorted(
            filter_files(PROCESS_DIRECTORY, ('dng', )))
        tests_dng_files = [
            os.path.join(self._temporary_directory,
                         os.path.basename(reference_dng_file))
            for reference_dng_file in reference_dng_files
        ]
        for reference_dng_file, tests_dng_file in zip(reference_dng_files,
                                                      tests_dng_files):
            shutil.copyfile(reference_dng_file, tests_dng_file)

        reference_zip_files = sorted(
            filter_files(PROCESS_DIRECTORY, ('zip', )))

        for reference_zip_file in reference_zip_files:
            with zipfile.ZipFile(reference_zip_file) as zip_file:
                tiff_file_name = os.path.basename(reference_zip_file).replace(
                    '.zip', '')
                with open(
                        os.path.join(self._temporary_directory,
                                     tiff_file_name),
                        'wb') as reference_tiff_file:
                    reference_tiff_file.write(zip_file.read(tiff_file_name))

        reference_tiff_files = sorted(
            filter_files(self._temporary_directory, ('tiff', )))

        # for reference_tiff_file in reference_tiff_files:
        #     os.chdir(os.path.dirname(reference_tiff_file))
        #     with zipfile.ZipFile(
        #             '{0}.zip'.format(reference_tiff_file),
        #             mode='w') as zip_file:
        #         zip_file.write(
        #             os.path.basename(reference_tiff_file),
        #             compress_type=zipfile.ZIP_DEFLATED)
        #         os.remove(reference_tiff_file)

        test_tiff_files = sorted(
            convert_dng_files_to_intermediate_files(tests_dng_files,
                                                    self._temporary_directory))

        for test_tiff_file, reference_tiff_file in zip(test_tiff_files,
                                                       reference_tiff_files):
            np.testing.assert_almost_equal(
                read_image(str(test_tiff_file)),
                read_image(str(reference_tiff_file)),
                decimal=7)


class TestReadDngFilesExifTags(unittest.TestCase):
    """
    Defines :func:`colour_hdri.process.adobe_dng.\
read_dng_files_exif_tags` definition unit tests methods.
    """

    def test_read_dng_files_exif_tags(self):
        """
        Tests :func:`colour_hdri.process.adobe_dng.\
read_dng_files_exif_tags` definition.
        """

        reference_dng_files = sorted(
            filter_files(PROCESS_DIRECTORY, ('dng', )))
        exif_tags = read_dng_files_exif_tags(reference_dng_files)
        self.assertEqual(len(exif_tags), 3)
        self.assertIn('EXIF', exif_tags[0])
        self.assertIn('Make', exif_tags[0]['EXIF'])

        self.assertAlmostEquals(
            exif_tags[0]['EXIF']['Exposure Time'], 0.12500000, places=7)

        np.testing.assert_array_equal(
            exif_tags[0]['EXIF']['Reduction Matrix 1'], np.identity(3))


if __name__ == '__main__':
    unittest.main()
