# -*- coding: utf-8 -*-

import os
from room import *

class GeneratorError(Exception):
    pass

class Generator:

    def __init__(self, l = []):

        self.enemy = {}
        self.trapped = {}
        self.challange = {}
        self.boss = {}
        self.armory = {}
        self.shop = {}
        self.spawn = {}
        self.wall = {}
        self.all = {'enemy': self.enemy, 'trapped':self.trapped, 'challenge':self.challange, 'boss': self.boss, 'armory': self.armory, 'shop': self.shop, 'spawn': self.spawn}
        self.sort(l)

    def add(self, room):
        if not isinstance(room, (Room, Wall)):
            raise GeneratorError("Generator only accepts 'Room' class objects")
        if room.type != 'wall':
            if room.floor in self.all[room.type].keys():
                self.all[room.type][room.floor].append(room)
            else:
                self.all[room.type][room.floor] = [room]
        else:
            if room.wall_type in self.wall.keys():
                self.wall[room.wall_type].append(room)
            else:
                self.wall[room.wall_type] = [room]

    def sort(self, l):
        if isinstance(l, list):
            for i,e in enumerate(l):
                if isinstance(e, list):
                    self.sort(e)
                elif isinstance(e, Room):
                    self.add(e)
                else:
                    raise Generator(f'Element in l[{i}] is not an Room')
        else:
            raise Generator("must be give a list of Rooms,a Room or a list with list of Rooms")

    def make(self):
        for type in self.all:
            path = f'../rooms_py/functions/{type}'
            if not os.path.exists(path):
                os.makedirs(path)
                print("Directory ", path , " Created ")

            self.floor_sort(type)

            for floor in self.all[type]:
                self.room_sort(type, floor)

        self.make_walls()

    def make_walls(self):
        path = '../rooms_py/functions/wall'
        if not os.path.exists(path):
            os.makedirs(path)
            print("Directory ", path , " Created ")

        with open('../rooms_py/functions/wall/floor_sort.mcfunction', 'w') as f:
            for type in self.wall:
                f.write(f'execute if entity @s[tag={type}] run function rooms_py:wall/{type}\n')

                l = []
                wall:Wall
                min_weight = 1
                max_weight = 0
                for wall in self.wall[type]:
                    max_weight += wall.weight
                    ifRND = f"if score #rnd dungeon matches {min_weight}..{max_weight} " if len(self.wall[type]) > 1 else ""
                    l += [
                        f'execute if entity @s[tag=north] {ifRND}run place template rooms:wall/{wall.wall_type}_{wall.id} ~1 ~ ~ clockwise_90 front_back\n'
                        f'execute if entity @s[tag=south] {ifRND}run place template rooms:wall/{wall.wall_type}_{wall.id} ~1 ~ ~ clockwise_90\n'
                        f'execute if entity @s[tag=east] {ifRND}run place template rooms:wall/{wall.wall_type}_{wall.id} ~ ~ ~-1 none\n'
                        f'execute if entity @s[tag=west] {ifRND}run place template rooms:wall/{wall.wall_type}_{wall.id} ~ ~ ~-1 none front_back\n\n'
                    ]
                    min_weight = max_weight + 1

                if len(self.wall[type]) > 1:
                    l = [f"execute store result score #rnd dungeon run random value 1..{max_weight}\n\n"] + l

                with open(f'../rooms_py/functions/wall/{type}.mcfunction', 'w') as f2:
                    f2.writelines(l)

            f.write("\nkill @s")

    def floor_sort(self, type):
        f = open(f'../rooms_py/functions/{type}/floor_sort.mcfunction', 'w')
        for floor in self.all[type]:
            f.write(f'execute if score floor dungeon matches {floor} run function rooms_py:{type}/floor_{floor}\n')
        f.close()

    def room_sort(self, type, floor):
        l = []
        room:Room
        min_weight = 1
        max_weight = 0
        for room in self.all[type][floor]:
            max_weight += room.weight
            ifRND = f"if score #rnd dungeon matches {min_weight}..{max_weight} " if len(self.all[type][floor]) > 1 else ""
            l += [
                f'execute {ifRND}run place template rooms:floor_{floor}/{type}_{room.id} ~ ~ ~\n',
                f'execute {ifRND}run tag @s add {room.id}\n\n'
            ]
            for tag in room.tags:
                l += [f'execute if score #rnd dungeon matches {min_weight}..{max_weight}  run tag @s add {tag}\n']
            min_weight = max_weight +1
        
        if len(self.all[type][floor]) > 1:
            l = [f"execute store result score #rnd dungeon run random value 1..{max_weight}\n\n"] + l

        with open(f'../rooms_py/functions/{type}/floor_{floor}.mcfunction', 'w') as f:
            f.writelines(l)