import itertools



dict_synonyms = {"box": ["container", "crate", "chest"],
    "key": ["passcode", "lock-opener", "unlocker"],
    "ball": ["sphere", "globe", "orb"],
    "door": ["portal", "gate", "hatch"],
    "blue": ["azure", "cobalt", "navy"],
    "red": ["scarlet", "crimson", "ruby"],
    "green": ["emerald", "jade", "lime"],
    "yellow": ["golden", "amber", "canary"],
    "purple": ["violet", "lavender","mauve"],
    "grey": ["ash", "charcoal", "silver"],
}



def give_synonyms(object):
    if len(object) ==  2:
        color = object[0]
        object = object[1]
        object_list = dict_synonyms[object]
        color_list = dict_synonyms[color]
        return  [ f"{x[0]} {x[1]}" for x in itertools.product(color_list, object_list)]
        
    elif len(object) == 1:
        object = object[0]
        object_list = dict_synonyms[object]
        return object_list
        
    else:
        raise ValueError(f"Object {object} not recognized")


def generate_alternative_goal(goal):


    if "go to the tile" in goal:
        coord = goal.split("(")[1].split(")")[0]
        
        formulations = [ lambda x : f"move to the location at coordinate ({x})",
                         lambda x : f"reach the position at ({x})",
                         lambda x : f"navigate to the point ({x})",            
        ]
    
        return [ f(coord) for f in formulations]
    
    elif "pick up" in goal:
        if "the " in goal:
            goal = goal.replace("the ","a ")
        
        
        formulations = [lambda x : f"grab a {x}",
                         lambda x : f"acquire a {x}",
                         lambda x : f"collect a {x}",
        ]
        
        
        object = goal.split("a ")[1].strip().split(" ")
  
        object_list = give_synonyms(object)
        return[ f(x) for x in object_list for f in formulations]
            
    
    
    elif "go to" in goal:
        if "the " in goal:
            goal = goal.replace("the ","a ")
        object = goal.split("a ")[1].strip().split(" ")
        
        formulations = [ lambda x : f"move to a {x}",
                         lambda x : f"reach a {x}",
                         lambda x : f"navigate to a {x}",            
        ]
    
        object_list = give_synonyms(object)
        return [ f(x) for x in object_list for f in formulations]
    
    elif "open" in goal:
        if "the " in goal:
            goal = goal.replace("the ","a ")
        
        formulations = [ lambda x : f"push a {x} open",
                         lambda x : f"swing open a {x}",
        ]
        
        object = goal.split("a ")[1].strip().split(" ")
        object_list = give_synonyms(object)
        return [ f(x) for x in object_list for f in formulations]
    
    
    elif "put" in goal:
        if "the " in goal:
            goal = goal.replace("the ","a ")
            
        formulations = [ lambda x,y : f"set a {x} and a {y} next to each other",
                         lambda x,y : f"position a {x} alongside a {y}",
                         lambda x,y : f"place a {x} beside a {y}",            
        ]
        
        object1 = goal.split("next to")[0].split("a ")[1].strip().split(" ")
        object2 = goal.split("next to")[1].strip().split("a ")[1].strip().split(" ") 

        object1_list = give_synonyms(object1)
        object2_list = give_synonyms(object2)
        
        return [ f(x,y) for x,y in itertools.product(object1_list, object2_list) for f in formulations]
    else:
        raise ValueError(f"Goal {goal} not recognized")
    

def reverse_alternative_goal(goal):
    if "move to the location at coordinate" in goal:
        coord = goal.split("(")[1].split(")")[0]
        return f"go to the tile ({coord})"
    
    elif "grab a" in goal:
        object = goal.split("grab a ")[1].strip()
        return f"pick up a {object}"
    
    elif "move to a" in goal:
        object = goal.split("move to a ")[1].strip()
        return f"go to a {object}"
    
    elif "push a" in goal:
        object = goal.split("push a ")[1].split(" open")[0].strip()
        return f"open the {object}"
    
    elif "set a" in goal:
        object1 = goal.split("set a ")[1].split(" and a ")[0].strip()
        object2 = goal.split("set a ")[1].split(" and a ")[1].strip()
        return f"put a {object1} next to a {object2}"
    else:
        raise ValueError(f"Goal {goal} not recognized")