"""Small offline checks for lean-package native artwork paths."""
import ast
from pathlib import Path
import struct
import sys
import unittest
from unittest.mock import patch
from urllib.parse import unquote

sys.path.insert(0, str(Path(__file__).resolve().parent))
import stubs
stubs.install()

from wcs.ui import assets, chip_strip

ROOT = Path(__file__).resolve().parents[2]
ARCHIVE = Path('/Applications/Kodi.app/Contents/Resources/Kodi/addons/skin.estuary/media/Textures.xbt')


class AssetPathTests(unittest.TestCase):
    def test_archive_is_translated_then_fully_quoted_on_each_platform(self):
        for path in ('/Applications/Kodi app/Český/addons/skin.estuary/media/Textures.xbt',
                     r'C:\Program Files\Kodi\addons\skin.estuary\media\Textures.xbt'):
            with self.subTest(path=path), patch.object(assets.xbmcvfs, 'translatePath', return_value=path) as translate:
                prefix = assets.prefix()
                translate.assert_called_once_with(assets.ARCHIVE_PATH)
                self.assertTrue(prefix.startswith('xbt://'))
                self.assertTrue(prefix.endswith('/'))
                host = prefix[len('xbt://'):-1]
                self.assertNotIn('/', host)
                self.assertNotIn('\\', host)
                self.assertNotIn(' ', host)
                self.assertEqual(unquote(host), path)

    def test_static_map_and_logo_aliases_are_ast_readable(self):
        tree = ast.parse((ROOT / 'wcs/ui/assets.py').read_text())
        values = {n.targets[0].id: ast.literal_eval(n.value) for n in tree.body
                  if isinstance(n, ast.Assign)}
        self.assertEqual(values['NATIVE_MAP'], assets.NATIVE_MAP)
        self.assertEqual(values['LOGO_ALIASES'], assets.LOGO_ALIASES)

    def test_full_joined_paths_and_dynamic_card_names_resolve(self):
        expected = 'xbt://archive/defaultmovies.png'
        with patch.object(assets, 'prefix', return_value='xbt://archive/'):
            for name in ('ai_card_movies.png', 'resources/media/ai_card_movies.png',
                         '/Users/Standa/Add on/resources/media/ai_card_movies.png',
                         r'C:\Kodi\addons\plugin.video.milionar\resources\media\ai_card_movies.png',
                         'special://home/addons/plugin.video.milionar/resources/media/ai_card_movies.png'):
                self.assertEqual(assets.native(name), expected)
            self.assertEqual(assets.native('DefaultSearch.png'), 'xbt://archive/defaultaddonssearch.png')
            self.assertEqual(assets.native('DefaultProgram.png'), 'xbt://archive/defaultprogram.png')
            self.assertEqual(assets.native('Icons/Search.png'), 'xbt://archive/icons/search.png')

    def test_unrelated_art_and_generated_profile_images_are_preserved(self):
        for name in (None, '', 'https://example.com/resources/media/ai_card_movies.png',
                     'image://https%3a%2f%2fexample.com/a.png/',
                     'special://profile/addon_data/plugin.video.milionar/cache/chips/chips_42.png',
                     '/tmp/chips_42.png', r'C:\Kodi\cache\chips_42.png',
                     'xbt://archive/defaultmovies.png'):
            self.assertEqual(assets.native(name), name)

    def test_all_logo_aliases_share_one_packaged_image(self):
        for alias in assets.LOGO_ALIASES:
            self.assertEqual(assets.native(alias), assets.LOGO_PATH)
            self.assertEqual(assets.native('/addon/' + alias), assets.LOGO_PATH)

    @unittest.skip('lean native-texture packaging was replaced by shipping the tree unchanged (scripts/build_zip.sh)')
    def test_source_media_has_a_fallback_except_manifest_screenshots(self):
        for image in (ROOT / 'resources/media').rglob('*'):
            if image.suffix.lower() not in ('.png', '.jpg', '.jpeg'):
                continue
            key = image.relative_to(ROOT / 'resources/media').as_posix()
            if key.startswith('screenshots/') or key in assets.LOGO_ALIASES:
                continue
            self.assertIn(key, assets.NATIVE_MAP)

    @unittest.skipUnless(ARCHIVE.exists(), 'Native Kodi archive is not installed on this host')
    def test_every_mapped_texture_exists_in_installed_xbt_header(self):
        names = set()
        with ARCHIVE.open('rb') as archive:
            self.assertEqual(archive.read(5), b'XBTF2')
            count = struct.unpack('<I', archive.read(4))[0]
            for _ in range(count):
                names.add(archive.read(256).split(b'\0', 1)[0].decode())
                _, frames = struct.unpack('<II', archive.read(8))
                archive.seek(frames * 40, 1)
        self.assertFalse(set(assets.NATIVE_MAP.values()) - names)

    def test_chip_font_uses_kodi_and_invalidates_bundled_font_cache(self):
        self.assertEqual(chip_strip._FONT_FILE, 'special://xbmc/media/Fonts/arial.ttf')
        self.assertEqual(chip_strip._VERSION, '4')


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