# Path: planner/operators.py
# class MacroOperator(object):
#   def __init__(self, *operators):
#     self.operators = tuple(operators)
#     self.cost = sum(operator.cost for operator in operators)
#   def __contains__(self, state):
#     return self(state) is not None
#   def __call__(self, state):
#     states = [state]
#     for operator in self.operators:
#       new_state = operator(states[-1])
#       if new_state is None: return None
#       states.append(new_state)
#     return states
#   def __iter__(self):
#     return (operator for operator in self.operators)
#   def __len__(self):
#     return len(self.operators)
#   def __eq__(self, other):
#     if type(self) != type(other): return False
#     return self.operators == other.operators
#   def __ne__(self, other):
#     return not self == other
#   def __hash__(self):
#     return hash((self.__class__, self.operators))
#   def __str__(self):
#     return self.__class__.__name__ + str_object(self.operators)
#   __repr__ = __str__
# 
# Path: planner/states.py
# class PartialState(SinglePrintObject):
#   #__slots__ = ('conditions',)
#   def __init__(self, conditions):
#     HashObject.__init__(self)
#     self.conditions = tuple(conditions)
#   def __contains__(self, state):
#     return all(state in condition for condition in self.conditions)
#   def __iter__(self):
#     for condition in self.conditions:
#       yield condition
#   def __len__(self):
#     return len(self.conditions)


from time import time
from planner.operators import MacroOperator
from planner.states import PartialState


def incremental_goal_addition(start, goal, search): # Replace generator_fn with state_space
  start_time = time()
  operators = []
  current = start # Allow starting at start state each time
  for i in range(len(goal)):
    plan_data, _ = search(current, PartialState(goal.conditions[:i+1]))
    if plan_data is None: return None, SearchData(time() - start_time, None, None)
    operators += plan_data.operators
    current = MacroOperator(*plan_data.operators)(current)[-1]
    if current in goal: break
    print(50*'-', '\n')


# Path: planner/operators.py
# class MacroOperator(object):
#   def __init__(self, *operators):
#     self.operators = tuple(operators)
#     self.cost = sum(operator.cost for operator in operators)
#   def __contains__(self, state):
#     return self(state) is not None
#   def __call__(self, state):
#     states = [state]
#     for operator in self.operators:
#       new_state = operator(states[-1])
#       if new_state is None: return None
#       states.append(new_state)
#     return states
#   def __iter__(self):
#     return (operator for operator in self.operators)
#   def __len__(self):
#     return len(self.operators)
#   def __eq__(self, other):
#     if type(self) != type(other): return False
#     return self.operators == other.operators
#   def __ne__(self, other):
#     return not self == other
#   def __hash__(self):
#     return hash((self.__class__, self.operators))
#   def __str__(self):
#     return self.__class__.__name__ + str_object(self.operators)
#   __repr__ = __str__
# 
# Path: planner/states.py
# class PartialState(SinglePrintObject):
#   #__slots__ = ('conditions',)
#   def __init__(self, conditions):
#     HashObject.__init__(self)
#     self.conditions = tuple(conditions)
#   def __contains__(self, state):
#     return all(state in condition for condition in self.conditions)
#   def __iter__(self):
#     for condition in self.conditions:
#       yield condition
#   def __len__(self):
#     return len(self.conditions)


# Path: planner/meta/incremental_goal_addition.py
from time import time
from planner.operators import MacroOperator
from planner.states import PartialState



def incremental_goal_addition(start, goal, search): # Replace generator_fn with state_space
  start_time = time()
  operators = []
  current = start # Allow starting at start state each time
  for i in range(len(goal)):
    plan_data, _ = search(current, PartialState(goal.conditions[:i+1]))
    if plan_data is None: return None, SearchData(time() - start_time, None, None)
    operators += plan_data.operators
    current = MacroOperator(*plan_data.operators)(current)[-1]
    if current in goal: break
    print(50*'-', '\n')


  if current not in goal: return None, SearchData(time() - start_time, None, None)