from typing import List
from ..report import Report

import asyncio
import logging
logger = logging.getLogger(__name__)


class TabsGroup(Report):
    """ Tabs group report class """

    report_type = 'TABS'

    default_properties = dict(
        **Report.default_properties,
        tabs=dict(),
        sticky=False,
        variant='enclosedSolidRounded',
    )

    def __init__(self, *args, **kwargs):
        self.dirty = False
        super().__init__(*args, **kwargs)

    async def update(self, *args, **kwargs) -> bool:
        """ Update the tabs group on the server
        :return: True if the tabs group was updated, False otherwise
        """
        if not self.dirty:
            return False
        self.dirty = False
        await super().update()
        return True

    async def delete(self):
        """ Delete the tabs group from the server and all its children """
        delete_tasks = []
        for tab_dict in self['properties']['tabs'].values():
            for rd_id in tab_dict['reportIds']:
                delete_tasks.append(self._base_resource.parent.delete_component(rd_id))
        await asyncio.gather(*delete_tasks)
        await super().delete()

    def add_tab(self, tab: str):
        """ Add tab to the tabs group without saving it to the server
        :param tab: tab name
        """
        if tab in self['properties']['tabs']:
            return
        self['properties']['tabs'][tab] = {'order': len(self['properties']['tabs']), 'reportIds': []}
        self.dirty = True

    def add_report(self, tab: str, report: Report):
        """ Add report to the tabs group without saving it to the server
        :param tab: tab name
        :param report: report to add
        """
        self.add_tab(tab)

        if report['id'] in self['properties']['tabs'][tab]['reportIds']:
            logger.warning(f"Report {report['id']} already in tab {tab}")
            return

        self['properties']['tabs'][tab]['reportIds'].append(report['id'])
        self.dirty = True

    def remove_report(self, tab: str, report: Report):
        """ Remove report from the tabs group without saving it to the server
        :param tab: tab name
        :param report: report to remove
        """

        if tab not in self['properties']['tabs']:
            logger.warning(f"Tab {tab} not found")
            return

        if report['id'] not in self['properties']['tabs'][tab]['reportIds']:
            logger.warning(f"Report {report['id']} not in tab {tab}")
            return

        self['properties']['tabs'][tab]['reportIds'].remove(report['id'])
        self.dirty = True

    def change_tabs_order(self, tabs: List[str]):
        """ Change tabs order without saving it to the server
        :param tabs: list of tabs in the new order
        """
        all_tabs = list(self['properties']['tabs'].keys())

        for i, tab in enumerate(tabs):
            if tab not in self['properties']['tabs']:
                logger.warning(f"Tab {tab} not found")
                continue
            all_tabs.remove(tab)
            self['properties']['tabs'][tab]['order'] = i

        for i, tab in enumerate(all_tabs):
            self['properties']['tabs'][tab]['order'] = i + len(tabs)
        self.dirty = True

    def has_report(self, report: Report):
        """ Check if report is in the tabs group
        :param report: report to check
        """
        for tab in self['properties']['tabs'].values():
            if report['id'] in tab['reportIds']:
                return True
        return False

    def clear_content(self):
        """ Remove all reports from the tabs group without saving it to the server """
        self['properties']['tabs'] = dict()
        self.dirty = True
