from src.World import *
from src.Map import *

def from_where(head_pos, next_head):
    if head_pos + Vector2D(1, 0) == next_head:
        return 'u' #r, l, d must be checked
    if head_pos + Vector2D(0, 1) == next_head:
        return 'l' #u ,d, r, must be checked
    if head_pos + Vector2D(-1, 0) == next_head:
        return 'd' #r, l, u must be checked
    if head_pos + Vector2D(0, -1) == next_head:
        return 'r' #u, d, l, must be checked

def is_surrounded(world: World, next_head, open_side):
    if open_side == 'u':
        if next_head + Vector2D(0, 1) in Map.get_obstacles(world) and next_head + Vector2D(0, -1) in Map.get_obstacles(world) and next_head + Vector2D(1, 0) in Map.get_obstacles(world):
            return True
    if open_side == 'l':
        if next_head + Vector2D(-1, 0) in Map.get_obstacles(world) and next_head + Vector2D(1, 0) in Map.get_obstacles(world) and next_head + Vector2D(0, 1) in Map.get_obstacles(world):
            return True
    if open_side == 'd':
        if next_head + Vector2D(0, 1) in Map.get_obstacles(world) and next_head + Vector2D(0, -1) in Map.get_obstacles(world) and next_head + Vector2D(-1, 0) in Map.get_obstacles(world):
            return True
    if open_side == 'r':
        if next_head + Vector2D(-1, 0) in Map.get_obstacles(world) and next_head + Vector2D(1, 0) in Map.get_obstacles(world) and next_head + Vector2D(0, -1) in Map.get_obstacles(world):
            return True
    return False

def is_risky(world: World, next_head):
    snake_heads = Map.get_snake_heads(world)
    for s in snake_heads:
        # if s.is_near(next_head):
        #     return True
        if next_head.dist(s) <= 2 and next_head.dist(world.goal_position) < s.dist(world.goal_position):
            print('is risky')
            return True
    return False

def get_action(world: World):
    head_pos = world.get_self().get_head()
    next_head = []
    next_head.append(head_pos + Vector2D(1, 0))  #d
    next_head.append(head_pos + Vector2D(0, 1))  #r
    next_head.append(head_pos + Vector2D(-1, 0)) #u
    next_head.append(head_pos + Vector2D(0, -1)) #l
    next_head_ok = [True, True, True, True]

    h_number = 0
    for h in next_head:
        accident = False
        if h in Map.get_obstacles(world):
            accident = True
            print('obstacle')
        if accident:
            next_head_ok[h_number] = False
        h_number += 1

    min_dist = 1000
    h_best = -1
    h_safe = -1
    h_risky = -1
    for h in range(4):
        if not next_head_ok[h]:
            continue
        dist = next_head[h].dist(world.goal_position)
        if dist < min_dist:
            if not is_surrounded(world, next_head[h], from_where(head_pos, next_head[h])):
                if not is_risky(world, next_head[h]):
                    min_dist = dist
                    h_best = h
                else:
                    h_risky = h
        else:
            if not is_surrounded(world, next_head[h], from_where(head_pos, next_head[h])):
                if not is_risky(world, next_head[h]):
                    h_safe = h

    debug = 0
    for s in world.snakes:
        debug += 1
    print('debug', debug)
    print(h_best)
    print('cycle', world.cycle)
    print("salam")

    if h_best == -1:
        if h_safe != -1:
            h_best = h_safe
        else:
            h_best = h_risky

    actions = ['d', 'r', 'u', 'l']
    if h_best > 0:
        return actions[h_best]

    # if h_safe > 0:
    #     return actions[h_safe]
    # if h_risky > 0:
    #     return actions[h_risky]
    return actions[0]





















# from src.World import *
# from src.Map import *
# from src.BFS import *
# from src.Node import *
#
#
# def from_where(head_pos, next_head):
#     if head_pos + Vector2D(1, 0) == next_head:
#         return 'u' #r, l, d must be checked
#     if head_pos + Vector2D(0, 1) == next_head:
#         return 'l' #u ,d, r, must be checked
#     if head_pos + Vector2D(-1, 0) == next_head:
#         return 'd' #r, l, u must be checked
#     if head_pos + Vector2D(0, -1) == next_head:
#         return 'r' #u, d, l, must be checked
#
#
# def is_surrounded(world: World, next_head, open_side):
#     if open_side == 'u':
#         if next_head + Vector2D(0, 1) in Map.get_obstacles(world) and next_head + Vector2D(0, -1) in Map.get_obstacles(world) and next_head + Vector2D(1, 0) in Map.get_obstacles(world):
#             return True
#     if open_side == 'l':
#         if next_head + Vector2D(-1, 0) in Map.get_obstacles(world) and next_head + Vector2D(1, 0) in Map.get_obstacles(world) and next_head + Vector2D(0, 1) in Map.get_obstacles(world):
#             return True
#     if open_side == 'd':
#         if next_head + Vector2D(0, 1) in Map.get_obstacles(world) and next_head + Vector2D(0, -1) in Map.get_obstacles(world) and next_head + Vector2D(-1, 0) in Map.get_obstacles(world):
#             return True
#     if open_side == 'r':
#         if next_head + Vector2D(-1, 0) in Map.get_obstacles(world) and next_head + Vector2D(1, 0) in Map.get_obstacles(world) and next_head + Vector2D(0, -1) in Map.get_obstacles(world):
#             return True
#     return False
#
#
# def is_risky(world: World, next_head):
#     snake_heads = Map.get_snake_heads(world)
#     for s in snake_heads:
#         # if s.is_near(next_head):
#         #     return True
#         if next_head.dist(s) <= 2:
#             return True
#     return False
#
#
#
#
# def get_action(world: World):
#     head_pos = world.get_self().get_head()
#     next_head = []
#     next_head.append(head_pos + Vector2D(1, 0))  #d
#     next_head.append(head_pos + Vector2D(0, 1))  #r
#     next_head.append(head_pos + Vector2D(-1, 0)) #u
#     next_head.append(head_pos + Vector2D(0, -1)) #l
#     next_head_ok = [True, True, True, True]
#
#     h_number = 0
#     for h in next_head:
#         accident = False
#         if h in Map.get_obstacles(world):
#             accident = True
#             print('obstacle')
#         if accident:
#             next_head_ok[h_number] = False
#         h_number += 1
#
#     # print(next_head)
#     # print(next_head_ok)
#     min_dist = 1000
#     h_best = -1
#     h_safe = -1
#     h_risky = -1
#
#     # print('cycle', world.cycle)
#     # adj = BFS.makeGraph(world)
#
#     for h in range(4):
#         if not next_head_ok[h]:
#             continue
#
#         # BFS.prepro()
#         # st = Node(BFS.idOfSquare(head_pos.i, head_pos.j), None)
#         # dist = BFS.optDist(adj, st, BFS.idOfSquare(world.goal_position.i, world.goal_position.j))
#         dist = next_head[h].dist(world.goal_position)
#
#         if dist < min_dist:
#             # if not is_surrounded(world, next_head[h], from_where(head_pos, next_head[h])) and not is_risky(world, next_head[h]):
#             #     min_dist = dist
#             #     h_best = h
#
#             if not is_surrounded(world, next_head[h], from_where(head_pos, next_head[h])):
#                 min_dist = dist
#                 h_best = h
#
#         else:
#             if not is_surrounded(world, next_head[h], from_where(head_pos, next_head[h])):
#                 if not is_risky(world, next_head[h]):
#                     h_safe = h
#                 else:
#                     h_risky = h
#
#
#
#     print(h_best, h_safe, h_risky)
#     print('salaaam')
#     print(world.cycle)
#
#
#     actions = ['d', 'r', 'u', 'l']
#     if h_best > 0:
#         return actions[h_best]
#     if h_safe > 0:
#         return actions[h_safe]
#     if h_risky > 0:
#         return actions[h_risky]
#     return actions[0]
