#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This file is part of ROBOTGAME
#
# ROBOTGAME is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# ROBOTGAME is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# ROBOTGAME.  If not, see <http://www.gnu.org/licenses/>.
#
# ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
#
#                         teleportermap.py
#                     --------------------
#       date created : Mon Aug 13 2012
#          copyright : (C) 2012 Niels G. W. Serup
#      maintained by : Niels G. W. Serup <ns@metanohi.name>

"""
Logic for a map with invisible teleporters.
"""

from __future__ import print_function
import math
import random
import itertools

from robotgame.logic.direction import *
import robotgame.misc as misc

class Empty(object):
    pass

class Forbidden(object):
    pass

class Visited(object):
    pass

def generate_teleporter_map(width, height):
    m = [[Empty for _ in range(height)]
         for _ in range(width)]

    def _get(p):
        if p[0] < 0 or p[0] >= width or p[1] < 0 or p[1] >= height:
            return Forbidden
        return m[p[0]][p[1]]

    def _set(p, val):
        try:
            m[p[0]][p[1]] = val
        except IndexError:
            pass

    def insert_random_point_on_line(x):
        t = random.randrange(height)
        for y in itertools.chain(xrange(t), xrange(t + 1, height)):
            _set((x, y), Forbidden)
        _set((x, t), Visited)
        return (x, t)
    
    pos = insert_random_point_on_line(width - 1)

    while True:
        while True:
            if pos[0] == 1 and random.randint(0, height) == 0:
                break
            t, found = random.randrange(4), None
            for direc in all_directions[t:] + all_directions[:t]:
                npos = direc.next_pos(pos)
                if found is None and npos[0] != 0 and _get(npos) is Empty and (
                    (direc is Right and
                     len(filter(lambda c: c is Empty, m[pos[0]][:pos[1]] if
                                opos[1] > pos[1]
                                else m[pos[0]][pos[1] + 1:])) >= 2)
                    or direc is not Right):
                    found = npos
                    _set(npos, Visited)
                else:
                    if _get(npos) is Empty:
                        _set(npos, Forbidden)
            if found is None:
                break
            opos = pos
            pos = found
        if pos[0] == 1:
            break
        _set(pos, Forbidden)
        for direc in all_directions:
            npos = direc.next_pos(pos)
            if _get(npos) is Visited:
                pos = npos
                break
        
    _set((0, pos[1]), Visited)
    return m

def generate_teleporter_map2(width, height):
    tmap = generate_teleporter_map(width, height)
    res = set()
    for y in range(len(tmap[0])):
        for x in range(len(tmap)):
            if tmap[x][y] is Visited:
                res.add((x, y))
    return res

def generate_teleporter_map3(width, height):
    return set(itertools.product(range(width), range(height))) \
        - generate_teleporter_map2(width, height)

def print_map(tmap):
    for y in range(len(tmap[0])):
        for x in range(len(tmap)):
            c = tmap[x][y]
            print({Empty: '%',
                   Forbidden: '#',
                   Visited: '·'}[c], end='')
        print()

