"""JSON parser for Opta F1 feeds."""
from datetime import datetime
from typing import Any, Dict, Tuple

from ...base import MissingDataError
from .base import OptaJSONParser, assertget


class F1JSONParser(OptaJSONParser):
    """Extract data from a Opta F1 data stream.

    Parameters
    ----------
    path : str
        Path of the data file.
    """

    def _get_feed(self) -> Dict[str, Any]:
        for node in self.root:
            if 'OptaFeed' in node['data'].keys():
                return node
        raise MissingDataError

    def _get_doc(self) -> Dict[str, Any]:
        f1 = self._get_feed()
        data = assertget(f1, 'data')
        optafeed = assertget(data, 'OptaFeed')
        optadocument = assertget(optafeed, 'OptaDocument')
        return optadocument

    def extract_competitions(self) -> Dict[Tuple[int, int], Dict[str, Any]]:
        """Return a dictionary with all available competitions.

        Returns
        -------
        dict
            A mapping between (competion ID, season ID) tuples and the
            information available about each competition in the data stream.
        """
        optadocument = self._get_doc()
        attr = assertget(optadocument, '@attributes')
        competition_id = int(assertget(attr, 'competition_id'))
        season_id = int(assertget(attr, 'season_id'))
        competition = dict(
            # Fields required by the base schema
            season_id=season_id,
            season_name=str(assertget(attr, 'season_id')),
            competition_id=competition_id,
            competition_name=assertget(attr, 'competition_name'),
        )
        return {(competition_id, season_id): competition}

    def extract_games(self) -> Dict[int, Dict[str, Any]]:
        """Return a dictionary with all available games.

        Returns
        -------
        dict
            A mapping between game IDs and the information available about
            each game in the data stream.
        """
        optadocument = self._get_doc()
        attr = assertget(optadocument, '@attributes')
        matchdata = assertget(optadocument, 'MatchData')
        matches = {}
        for match in matchdata:
            matchattr = assertget(match, '@attributes')
            matchinfo = assertget(match, 'MatchInfo')
            matchinfoattr = assertget(matchinfo, '@attributes')
            game_id = int(assertget(matchattr, 'uID')[1:])
            matches[game_id] = dict(
                # Fields required by the base schema
                game_id=game_id,
                competition_id=int(assertget(attr, 'competition_id')),
                season_id=int(assertget(attr, 'season_id')),
                game_day=int(assertget(matchinfoattr, 'MatchDay')),
                game_date=datetime.strptime(assertget(matchinfo, 'Date'), '%Y-%m-%d %H:%M:%S'),
                # home_team_id=see below,
                # away_team_id=see below,
                # Optional fields
                # home_score=see below,
                # away_score=see below,
                # duration=?
                # referee=?
                # venue=?,
                # attendance=?
                # home_manager=?
                # away_manager=?
            )
            teamdata = assertget(match, 'TeamData')
            for team in teamdata:
                teamattr = assertget(team, '@attributes')
                side = assertget(teamattr, 'Side')
                teamid = assertget(teamattr, 'TeamRef')
                score = assertget(teamattr, 'Score')
                if side == 'Home':
                    matches[game_id]['home_team_id'] = int(teamid[1:])
                    matches[game_id]['home_score'] = int(score)
                else:
                    matches[game_id]['away_team_id'] = int(teamid[1:])
                    matches[game_id]['away_score'] = int(score)
        return matches
