import json
from typing import Optional

from level.Level import Level
from physics import ConstantsParser


class LevelManager:
    def __init__(self, level_dir: str):
        self.level_dir = level_dir
        self.levels = []

    def load_from_config(self, config_file: str):
        print('Loading levels from sprite sheet config file', config_file)
        config = json.load(open(config_file))

        for level_data in config:
            csv = self.parse_csv(self.level_dir + '/' + level_data['file'])
            level = Level(level_data['name'], level_data['theme'], level_data['abilities'], csv)
            self.levels.append(level)

    def parse_csv(self, file: str):
        csv_array = []
        with open(file) as csvfile:
            for row in csvfile:
                split_row = row.split(',')
                filtered_row = list(map(lambda x: x.replace('\n', ''), split_row))
                csv_array.append(filtered_row)
        return csv_array

    def get_levels_by_theme(self) -> dict[str, list[Level]]:
        levels_by_theme = {}
        for level in self.levels:
            if level.theme not in levels_by_theme:
                levels_by_theme[level.theme] = []
            levels_by_theme[level.theme].append(level)
        return levels_by_theme

    def find_next_level(self, level: Level) -> Optional[Level]:
        """
        Find the next element in the theme using THEME. If the last element from a theme is reached, the first element
        of the next theme is returned. If the last THEME is reached, return None.
        :param level:  The level to find the next level from
        :return:     The next level or None
        """
        levels_by_theme = self.get_levels_by_theme()
        theme_index = ConstantsParser.CONFIG.themes.index(level.theme)
        level_index = levels_by_theme[level.theme].index(level)

        if level_index + 1 < len(levels_by_theme[level.theme]):
            return levels_by_theme[level.theme][level_index + 1]
        elif theme_index + 1 < len(ConstantsParser.CONFIG.themes):
            return levels_by_theme[ConstantsParser.CONFIG.themes[theme_index + 1]][0]
        else:
            return None