"""Accent persistence, cancellation and shared branding contracts."""
import json
from pathlib import Path
import sys
import unittest
from unittest.mock import patch
import xml.etree.ElementTree as ET

sys.path.insert(0, str(Path(__file__).resolve().parent))
import stubs
stubs.install()
import xbmc
import xbmcgui
from wcs.skin import appearance

ROOT = Path(__file__).resolve().parents[2]


class AppearanceTests(unittest.TestCase):
    def select(self, index, current='SKINDEFAULT', skin='skin.milionar', result=True):
        with patch.object(xbmc, 'getSkinDir', return_value=skin, create=True), \
                patch.object(xbmc, 'getInfoLabel', return_value=current), \
                patch.object(xbmcgui.Dialog, 'select', return_value=index, create=True) as picker, \
                patch.object(xbmcgui, 'NOTIFICATION_ERROR', 'error', create=True), \
                patch.object(xbmc, 'executeJSONRPC', return_value=json.dumps({'result': result})) as rpc, \
                patch.object(appearance, '_swatch', return_value=''), \
                patch.object(xbmcgui.Dialog, 'notification') as notify:
            appearance.select_accent()
            return picker, rpc, notify

    def test_every_colour_persists_through_kodi(self):
        for index, (theme, _, _) in enumerate(appearance.PALETTE[1:], 1):
            with self.subTest(theme=theme):
                picker, rpc, _ = self.select(index, current='gold.xml')
                self.assertEqual(len(picker.call_args.args[1]), len(appearance.PALETTE))
                self.assertEqual(json.loads(rpc.call_args.args[0])['params'],
                                 {'setting': 'lookandfeel.skincolors', 'value': theme})

    def test_cancel_and_existing_colour_do_not_write(self):
        for index, current in [(-1, 'SKINDEFAULT'), (0, 'SKINDEFAULT'), (1, 'milionar-kodi-blue'),
                               (1, 'milionar-kodi-blue.xml')]:
            with self.subTest(index=index, current=current):
                _, rpc, _ = self.select(index, current)
                rpc.assert_not_called()

    def test_only_milionar_skin_can_apply_the_theme(self):
        picker, rpc, _ = self.select(1, skin='skin.estuary')
        picker.assert_not_called()
        rpc.assert_not_called()

    def test_failed_persistence_is_reported(self):
        _, _, notify = self.select(1, result=False)
        notify.assert_called_once()

    def test_own_theme_matches_picker(self):
        for theme, color, _ in appearance.PALETTE:
            if theme != 'milionar-kodi-blue.xml':
                continue
            colors = {item.attrib['name']: item.text for item in
                      ET.parse(ROOT / 'resources/skin.milionar/colors' / theme).getroot()}
            self.assertEqual(colors['button_focus'], 'FF' + color)
            self.assertEqual(colors['selected'], 'FF' + color)
            self.assertFalse({'primary_background', 'secondary_background', 'dialog_tint'} & colors.keys())

    def test_static_icons_are_the_exact_original_mark(self):
        mark = (ROOT / 'resources/media/brand/milionar-mark.png').read_bytes()
        for path in ['resources/skin.milionar/resources/icon.png',
                     'resources/skin.milionar/media/milionar/logo-mark-v1-final.png']:
            self.assertEqual((ROOT / path).read_bytes(), mark)


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