import cocos
import random
import pyglet

class World(cocos.tiles.RectMapLayer):

    def __init__(self):
        # Create tileset
        
        ground_tile = pyglet.image.load('img/ground.png')
        wall_tile = pyglet.image.load('img/wall.png')
        pavement_tile = pyglet.image.load('img/pavement.png')
        floor_tile = pyglet.image.load('img/floor.png')

        self.map_size = 50,50

        tileset = cocos.tiles.TileSet(0, None)
        tileset.add( {'passable':True, 'transparent':True} , ground_tile, 'ground')
        tileset.add( {'passable':False, 'transparent':False} , wall_tile, 'wall')
        tileset.add( {'passable':True, 'transparent':True} , pavement_tile, 'pavement')
        tileset.add( {'passable':True, 'transparent':True} , floor_tile, 'floor')


        self.streets = []

        cells = []
        self.things = []
        for i in range(self.map_size[0]):
            col = []
            col2 = []
            for j in range(self.map_size[1]):
                col.append('wall')
                col2.append([])
            cells.append(col)
            self.things.append(col2)


        street_x = random.randint(5,self.map_size[0]-4)
        street_y = random.randint(5,self.map_size[1]-4)


        self.make_road(cells, street_x, 0, (0,1), self.map_size[1])
        self.streets.append([street_x, 0, (0,1), self.map_size[1], 3, 3])

        self.make_road(cells, 0, street_y, (1,0), self.map_size[0], 5, 2)
        self.streets.append([0, street_y, (1,0), self.map_size[0], 5, 2])

        street_y = random.randint(2,self.map_size[0]-2)

        self.make_road(cells, street_x, street_y, (1,0), min(self.map_size[0]-street_x-1, 30), 1, 0)
        self.streets.append([street_x, street_y, (1,0), min(self.map_size[0]-street_x-1, 30),1,0])


        for b in range(20):
            self.make_building(cells)

        for i in range(len(cells)):
            for j in range(len(cells[0])):
                cells[i][j] = cocos.tiles.RectCell(i,j,32,32,{},tileset[cells[i][j]])



        super(World, self).__init__('map', 32, 32, cells)


    def make_road(self, cells, start_x, start_y, direction, length, width=3, pavement_width=3):

        for step in range(length):

            cur_x = start_x + step*direction[0]
            cur_y = start_y + step*direction[1]

            for k in range(pavement_width):
                cx = cur_x - (k+width/2+1) * abs(direction[1])
                cy = cur_y - (k+width/2+1) * abs(direction[0])
                if cells[cx][cy] == 'wall':
                    cells[cx][cy] = 'pavement'

                cx = cur_x + (k+width/2+1) * abs(direction[1])
                cy = cur_y + (k+width/2+1) * abs(direction[0])
                if cells[cx][cy] == 'wall':
                    cells[cx][cy] = 'pavement'

            for k in range(width):
                cx = cur_x + (k - width/2) * abs(direction[1])
                cy = cur_y + (k - width/2) * abs(direction[0])
                cells[cx][cy] = 'ground'

    def make_building(self, cells):
        road = self.streets[random.randint(0,len(self.streets)-1)]

        side = random.randint(0,1)*2 -1
        along = random.randint(3,road[3]-4)

        rdir = road[2]

        if abs(rdir[0] == 0):
            door_x = road[0]+side*(road[4]/2+road[5]+1)
            door_y = along + road[1]
        else:
            door_x = along + road[0]
            door_y = road[1]+side*(road[4]/2+road[5]+1)

        if cells[door_x][door_y] == 'wall':
            cells[door_x][door_y] = 'floor'

            max_size = random.randint(2,8)
            queue = []
            done = []

            if cells[door_x+side*abs(rdir[1])][door_y+side*abs(rdir[0])] == 'wall':
                queue.append((door_x+side*abs(rdir[1]),door_y+side*abs(rdir[0])))

            directions = [(-1,0),(1,0),(0,-1),(0,1)]

            while len(queue) > 0:
                to_remove = []

                cur = queue[0]
                #print queue
                #print max_size
                for d in directions:

                    if min(cur[0]+2*d[0], cur[0]+2*d[0]) >= 0 and \
                       cur[0]+2*d[0] < self.map_size[0] and \
                       cur[1]+2*d[1] < self.map_size[1] and \
                       d[0]*(cur[0]+d[0]) <= d[0]*(door_x+max_size*d[0]) and\
                       d[1]*(cur[1]+d[1]) <= d[1]*(door_y+max_size*d[1]) and\
                       cells[cur[0]+d[0]][cur[1]+d[1]] == 'wall' and \
                       cells[cur[0]+2*d[0]][cur[1]+2*d[1]] == 'wall':

                       newcell = (cur[0]+d[0],cur[1]+d[1])

                       if newcell not in queue and \
                          newcell not in done:
                            queue.append(newcell)
                    else:
                        pass#to_remove.append(d)
                for t in to_remove:
                    directions.remove(t)

                done.append(cur)
                queue.remove(cur)

            for d in done:
                cells[d[0]][d[1]] = 'floor'

    def get_viable_position(self):
        x = random.randint(0,self.map_size[0]-1)
        y = random.randint(0,self.map_size[1]-1)
        while not self.get_cell(x,y)['passable']:
            x = random.randint(0,self.map_size[0]-1)
            y = random.randint(0,self.map_size[1]-1) 
        return x,y           