"""Live checks confined to newly created disposable playlists/channels; no credentials in results."""
from types import SimpleNamespace
from uuid import uuid4

_UI_FIXTURES = []


class Inputs:
    value = ''
    selected = 0

    def input(self, *args, **kwargs):
        return self.value

    def select(self, *args, **kwargs):
        return self.selected

    def yesno(self, *args, **kwargs):
        return True

    def notification(self, *args, **kwargs):
        pass


def open_channel(kind, edit=False, fixture=False):
    """Open an existing last channel to verify selection/inheritance without changing data."""
    import xbmc
    import xbmcaddon
    from wcs.ai.MediaChannelManager import MediaChannelManager
    from wcs.skin.context import builtin
    manager = MediaChannelManager(xbmcaddon.Addon(), channel_type=kind)
    if fixture:
        for _ in range(2):
            channel = manager.create_channel('Kodi context check ' + uuid4().hex[:8])
            _UI_FIXTURES.append((kind, channel.id))
    channels = manager.get_all_channels()
    if not channels:
        return {'empty': True}
    selected = channels[-1]
    xbmc.executebuiltin(builtin({'action': 'my_cinema_dialog' if kind == 'cinema' else 'my_tv_dialog',
                                'channel_id': selected.id, 'edit': '1' if edit else '',
                                'ctx': 'mycinema:1' if kind == 'cinema' else 'mytv:1',
                                'ctxrow': 'widget_mycinema_channels' if kind == 'cinema' else 'widget_mytv_channels'}))
    return {'id': selected.id, 'name': selected.name, 'editor': edit}


def cleanup_ui():
    import xbmcaddon
    from wcs.ai.MediaChannelManager import MediaChannelManager
    count = len(_UI_FIXTURES)
    while _UI_FIXTURES:
        kind, identity = _UI_FIXTURES.pop()
        MediaChannelManager(xbmcaddon.Addon(), channel_type=kind).delete_channel(identity)
    return {'removed': count}


def verify_vinyl():
    from wcs.vinyl import client, context, widgets
    name = 'Kodi context check ' + uuid4().hex[:8]
    original_gui, original_xbmc, original_refresh = context.xbmcgui, context.xbmc, widgets.refresh
    inputs = Inputs()
    identity = None
    try:
        context.xbmcgui = SimpleNamespace(Dialog=lambda: inputs)
        context.xbmc = SimpleNamespace(executebuiltin=lambda value: None)
        widgets.refresh = lambda: None
        inputs.value = name
        context.run({'op': 'create_playlist'})
        own = [p for p in client.request('playlists')['playlists'] if p.get('is_owner')]
        identity = next(p['id'] for p in own if p['name'] == name)
        inputs.value = name + ' renamed'
        context.run({'op': 'rename_playlist', 'id': str(identity)})
        assert client.request('playlists/{}'.format(identity))['name'] == inputs.value
        songs = client.paged_songs('songs?sort=created_at&order=DESC')[:2]
        assert len(songs) == 2
        own = [p for p in client.request('playlists')['playlists'] if p.get('is_owner')]
        inputs.selected = next(i for i, p in enumerate(own) if p['id'] == identity)
        for song in songs:
            context.run({'op': 'add_playlist', 'kind': 'song', 'id': str(song['id'])})
        def ids():
            return [s['id'] for s in client.collection('playlist', identity)]
        assert ids() == [s['id'] for s in songs]
        context.run({'op': 'song_up', 'id': str(songs[1]['id']), 'parent_playlist': str(identity)})
        assert ids() == [songs[1]['id'], songs[0]['id']]
        context.run({'op': 'song_down', 'id': str(songs[1]['id']), 'parent_playlist': str(identity)})
        assert ids() == [s['id'] for s in songs]
        context.run({'op': 'remove_song', 'id': str(songs[0]['id']), 'parent_playlist': str(identity), 'name': 'check'})
        assert ids() == [songs[1]['id']]
        context.run({'op': 'favorite', 'kind': 'playlist', 'id': str(identity)})
        assert next(p for p in client.request('playlists')['playlists'] if p['id'] == identity)['is_favorite']
        context.run({'op': 'favorite', 'kind': 'playlist', 'id': str(identity)})
        assert not next(p for p in client.request('playlists')['playlists'] if p['id'] == identity)['is_favorite']
        context.run({'op': 'delete_playlist', 'id': str(identity)})
        assert not any(p['id'] == identity for p in client.request('playlists')['playlists'])
        identity = None
        return {'create': True, 'rename': True, 'add': True, 'reorder_both': True,
                'remove': True, 'favorite_both': True, 'delete': True}
    finally:
        context.xbmcgui, context.xbmc, widgets.refresh = original_gui, original_xbmc, original_refresh
        # Recover even if the create response failed after the server accepted it.
        leftovers = [p for p in client.request('playlists')['playlists']
                     if p.get('is_owner') and p['name'] in (name, name + ' renamed')]
        for playlist in leftovers:
            client.request('playlists/{}'.format(playlist['id']), 'DELETE')


def verify_channels():
    import xbmcaddon
    from wcs.ai.MediaChannelManager import MediaChannelManager
    from wcs.skin import channel_actions
    result = {}
    original_gui, original_xbmc = channel_actions.xbmcgui, channel_actions.xbmc
    inputs = Inputs()
    try:
        channel_actions.xbmcgui = SimpleNamespace(Dialog=lambda: inputs)
        channel_actions.xbmc = SimpleNamespace(executebuiltin=lambda value: None)
        for kind in ('tv', 'cinema'):
            def manager():
                return MediaChannelManager(xbmcaddon.Addon(), channel_type=kind)
            before = [ch.id for ch in manager().get_all_channels()]
            channel = manager().create_channel('Kodi context check ' + uuid4().hex[:8])
            try:
                inputs.value = channel.name + ' renamed'
                params = {'kind': kind, 'id': channel.id}
                channel_actions.run(dict(params, op='rename_channel'))
                assert manager().get_channel_by_id(channel.id).name == inputs.value
                inputs.selected = len(before)
                channel_actions.run(dict(params, op='move_channel'))
                assert manager().get_all_channels()[-1].id == channel.id
                channel_actions.run(dict(params, op='delete_channel'))
                assert [ch.id for ch in manager().get_all_channels()] == before
                result[kind] = {'rename': True, 'move': True, 'delete': True, 'existing_order_preserved': True}
            finally:
                manager().delete_channel(channel.id)
    finally:
        channel_actions.xbmcgui, channel_actions.xbmc = original_gui, original_xbmc
    return result
