# Path: planner/state_space.py
# class Plan(object):
#     def __init__(self, start, operators):
#         self.start = start
#         self.operators = operators
#     @property
#     def cost(self):
#         if not self.operators:
#             return 0
#         return sum(operator.cost for operator in self.operators)
#     @property
#     def length(self):
#         return len(self.operators)
#     @property
#     def priority(self):
#         return Priority(self.cost, self.length)
#     def __iter__(self):
#         return iter(self.operators)
#     def get_states(self):
#         states = [self.start]
#         for operator in self.operators:
#             #assert states[-1] in operator
#             #states.append(operator(states[-1]))
#             states.append(operator.apply(states[-1]))
#         return states
#     def get_derived_states(self, axioms):
#         states = [self.start]
#         derived_state, axiom_plan = derive_predicates(states[-1], axioms)
#         derived_states = [derived_state]
#         axiom_plans = [axiom_plan]
#         for operator in self.operators:
#             assert derived_states[-1] in operator
#             states.append(operator.apply(states[-1]))
#             derived_state, axiom_plan = derive_predicates(states[-1], axioms)
#             derived_states.append(derived_state)
#             axiom_plans.append(axiom_plan)
#         return derived_states, axiom_plans
#     def __str__(self):
#         s = '{name} | Cost: {self.cost} | Length {self.length}'.format(name=self.__class__.__name__, self=self)
#         for i, operator in enumerate(self.operators):
#             s += str_line('\n%d | '%(i+1), operator)
#         return s
#     __repr__ = __str__
# 
# Path: sas/states.py
# class Goal(PartialState): # TODO: unify PartialState and Goal
#   def __init__(self, values, test=lambda state: True):
#     self.conditions = values
#     self.test = test
#   def __eq__(self, other):
#     return (type(self) == type(other)) and (self.conditions == other.conditions)
#   def __ne__(self, other):
#     return not self == other
#   def __hash__(self):
#     return hash((self.__class__, frozenset(self.cond())))
#   def __str__(self):
#     return self.__class__.__name__ + str_object(self.conditions)
#   __repr__ = __str__


from planner.state_space import Plan
from sas.states import Goal
from copy import deepcopy
  for modified_operator in plan.operators:
    operator = modified_operator.original
    if state not in operator:
      #print(state, operator)
      #print()
      subplan, subdata = fixed_search(state, Goal(operator.conditions), operators, subsearch, hierarchy, level=level+1)
      if subplan is None:
        return None, None
      state = subplan.get_states()[-1]
      sequence += subplan.operators
    if operator != goal:
      state = operator(state)
      sequence.append(operator)
  return Plan(start, sequence), None # TODO - merge state-spaces

# TODO - some sort of recursion here on the subproblem in the event that the plan is satisfiable using a fair amount of preconditions
# While the plan to achieve the goal is empty, increase the level? As soon as you get something, then you continue
# Maybe there really is only one level which iterates upon the plan being trivially solved or something
def recursive_search(start, goal, operators, subsearch, hierarchy, level=0, goal_level=0):
  raise NotImplementedError()
  plan, state_space = subsearch(start, goal, operators)
  if plan is None:
    return None, None

  state = start
  sequence = []
  #for operator in plan.operators + [goal]: # TODO - should I assume that the last operator achieves the goal or not?
  for operator in plan.operators:
    if state not in operator:
      print(state, operator)

# Path: planner/state_space.py
# class Plan(object):
#     def __init__(self, start, operators):
#         self.start = start
#         self.operators = operators
#     @property
#     def cost(self):
#         if not self.operators:
#             return 0
#         return sum(operator.cost for operator in self.operators)
#     @property
#     def length(self):
#         return len(self.operators)
#     @property
#     def priority(self):
#         return Priority(self.cost, self.length)
#     def __iter__(self):
#         return iter(self.operators)
#     def get_states(self):
#         states = [self.start]
#         for operator in self.operators:
#             #assert states[-1] in operator
#             #states.append(operator(states[-1]))
#             states.append(operator.apply(states[-1]))
#         return states
#     def get_derived_states(self, axioms):
#         states = [self.start]
#         derived_state, axiom_plan = derive_predicates(states[-1], axioms)
#         derived_states = [derived_state]
#         axiom_plans = [axiom_plan]
#         for operator in self.operators:
#             assert derived_states[-1] in operator
#             states.append(operator.apply(states[-1]))
#             derived_state, axiom_plan = derive_predicates(states[-1], axioms)
#             derived_states.append(derived_state)
#             axiom_plans.append(axiom_plan)
#         return derived_states, axiom_plans
#     def __str__(self):
#         s = '{name} | Cost: {self.cost} | Length {self.length}'.format(name=self.__class__.__name__, self=self)
#         for i, operator in enumerate(self.operators):
#             s += str_line('\n%d | '%(i+1), operator)
#         return s
#     __repr__ = __str__
# 
# Path: sas/states.py
# class Goal(PartialState): # TODO: unify PartialState and Goal
#   def __init__(self, values, test=lambda state: True):
#     self.conditions = values
#     self.test = test
#   def __eq__(self, other):
#     return (type(self) == type(other)) and (self.conditions == other.conditions)
#   def __ne__(self, other):
#     return not self == other
#   def __hash__(self):
#     return hash((self.__class__, frozenset(self.cond())))
#   def __str__(self):
#     return self.__class__.__name__ + str_object(self.conditions)
#   __repr__ = __str__


# Path: planner/meta/forward_hierarchy.py
from planner.state_space import Plan
from sas.states import Goal
from copy import deepcopy

  for modified_operator in plan.operators:
    operator = modified_operator.original
    if state not in operator:
      #print(state, operator)
      #print()
      subplan, subdata = fixed_search(state, Goal(operator.conditions), operators, subsearch, hierarchy, level=level+1)
      if subplan is None:
        return None, None
      state = subplan.get_states()[-1]
      sequence += subplan.operators
    if operator != goal:
      state = operator(state)
      sequence.append(operator)
  return Plan(start, sequence), None # TODO - merge state-spaces

# TODO - some sort of recursion here on the subproblem in the event that the plan is satisfiable using a fair amount of preconditions
# While the plan to achieve the goal is empty, increase the level? As soon as you get something, then you continue
# Maybe there really is only one level which iterates upon the plan being trivially solved or something
def recursive_search(start, goal, operators, subsearch, hierarchy, level=0, goal_level=0):
  raise NotImplementedError()
  plan, state_space = subsearch(start, goal, operators)
  if plan is None:
    return None, None

  state = start
  sequence = []
  #for operator in plan.operators + [goal]: # TODO - should I assume that the last operator achieves the goal or not?
  for operator in plan.operators:
    if state not in operator:
      print(state, operator)

      subgoal = Goal(operator.conditions) # Goal-level different than new operator level or something