# -*- 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('Element in l[{0}] is not an Room'.format(i))
        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 = '../rooms_py/functions/{0}'.format(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('execute if entity @s[tag={0}] run function rooms_py:wall/{0}\n'.format(type))

            f2 = open('../rooms_py/functions/wall/{0}.mcfunction'.format(type), '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("scoreboard players set max rng {}\n".format(max_weight))
            f2.write("function rng:interval\n\n")

            min_weight = 1
            max_weight = 0
            for wall in walls:
                max_weight += wall.weight
                f2.write("""
execute if entity @s[tag=north] if score out rng matches {0}..{1} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{2}_{3}",posX:1,posY:0,posZ:0,rotation:"CLOCKWISE_90",mirror:"FRONT_BACK"}} replace
execute if entity @s[tag=south] if score out rng matches {0}..{1} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{2}_{3}",posX:1,posY:0,posZ:0,rotation:"CLOCKWISE_90"}} replace
execute if entity @s[tag=east] if score out rng matches {0}..{1} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{2}_{3}",posX:0,posY:0,posZ:-1,rotation:"NONE"}} replace
execute if entity @s[tag=west] if score out rng matches {0}..{1} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:wall/{2}_{3}",posX:0,posY:0,posZ:-1,mirror:"FRONT_BACK"}} replace\n""".format(min_weight, max_weight, wall.wall_type, wall.id))
                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('../rooms_py/functions/{0}/floor_sort.mcfunction'.format(type), 'w')
        for floor in self.all[type]:
            f.write('execute if score floor dungeon matches {0} run function rooms_py:{1}/floor_{0}\n'.format(floor, type))
        f.close()

    def room_sort(self, type, floor):
        f = open('../rooms_py/functions/{0}/floor_{1}.mcfunction'.format(type, floor), '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("scoreboard players set max rng {}\n".format(max_weight))
        f.write("function rng:interval\n\n")

        min_weight = 1
        max_weight = 0
        for room in rooms:
            max_weight += room.weight
            f.write('execute if score out rng matches {}..{} run setblock ~ ~ ~ structure_block{{mode:"LOAD",name:"rooms:floor_{}/{}_{}"}} replace\n'.format(min_weight, max_weight, floor, type, room.id))
            f.write('execute if score out rng matches {}..{} run tag @s add {}\n'.format(min_weight, max_weight, room.id))
            for tag in room.tags:
                f.write('execute if score out rng matches {}..{} run tag @s add {}\n'.format(min_weight, max_weight, tag))
            min_weight = max_weight +1
        f.close()
