# -*- 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 ")

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

            f2 = open(f'../rooms_py/functions/wall/{type}.mcfunction', 'w')
            walls = self.wall[type]

            max_weight = 0
            for wall in walls:
                max_weight += wall.weight
            f2.write("scoreboard players set min rng 1\n")
            f2.write(f"scoreboard players set max rng {max_weight}\n")
            f2.write("function rng:interval\n\n")

            min_weight = 1
            max_weight = 0
            for wall in walls:
                max_weight += wall.weight
                f2.write(f"""
execute if entity @s[tag=north] if score out rng matches {min_weight}..{max_weight} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{wall.wall_type}_{wall.id}",posX:1,posY:0,posZ:0,rotation:"CLOCKWISE_90",mirror:"FRONT_BACK"}} replace
execute if entity @s[tag=south] if score out rng matches {min_weight}..{max_weight} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{wall.wall_type}_{wall.id}",posX:1,posY:0,posZ:0,rotation:"CLOCKWISE_90"}} replace
execute if entity @s[tag=east] if score out rng matches {min_weight}..{max_weight} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{wall.wall_type}_{wall.id}",posX:0,posY:0,posZ:-1,rotation:"NONE"}} replace
execute if entity @s[tag=west] if score out rng matches {min_weight}..{max_weight} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{wall.wall_type}_{wall.id}",posX:0,posY:0,posZ:-1,mirror:"FRONT_BACK"}} replace\n""")
                min_weight = max_weight + 1
            f2.close()

        f.write("\n# Activate structure blocks")
        f.write("\nsetblock ~ ~1 ~ redstone_block replace")
        f.write("\n\n# Remove marker")
        f.write("\nkill @s")
        f.close()

    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):
        f = open(f'../rooms_py/functions/{type}/floor_{floor}.mcfunction', 'w')
        rooms = self.all[type][floor]

        max_weight = 0
        for room in rooms:
            max_weight += room.weight
        f.write("scoreboard players set min rng 1\n")
        f.write(f"scoreboard players set max rng {max_weight}\n")
        f.write("function rng:interval\n\n")

        min_weight = 1
        max_weight = 0
        for room in rooms:
            max_weight += room.weight
            f.write(f'execute if score out rng matches {min_weight}..{max_weight} run place template rooms:floor_{floor}/{type}_{room.id} ~ ~ ~\n')
            f.write(f'execute if score out rng matches {min_weight}..{max_weight} run tag @s add {room.id}\n')
            for tag in room.tags:
                f.write(f'execute if score out rng matches {min_weight}..{max_weight}  run tag @s add {tag}\n')
            min_weight = max_weight +1
        f.close()
