# Implementation of the module {block}.
# Last edited on 2021-03-21 13:23:50 by jstolfi

import block
import path
import move
import move_parms
import contact
import job_parms
import hacks
import rn 
import pyx
import sys
from math import sqrt, floor, ceil, sin, cos, acos, pi, nan,  inf

class Block_IMP:
  # A {Block_IMP} object {bc} has a list {bc.OPHS} of {nch} one or more oriented
  # paths that are the choices.
  
  def __init__(self, OPHS ):
    self.OPHS = OPHS
    # Fields for the heuristic:
    self.used = False
    self.cts = []

def from_paths(OPHS):
  assert type(OPHS) == list or type(OPHS) == tuple
  assert len(OPHS) >  0
  bc = block.Block(tuple(OPHS))
  return bc

def nchoices(bc):
  #assert isinstance(bc, block.Block)
  n = len(bc.OPHS)
  return n
  
def choice(bc, ich):
  #assert isinstance(bc, block.Block)
  #n = len(bc.OPHS)
  #assert ich >= 0 and ich < n
  och = bc.OPHS[ich] # Choice of the elements before reversal.
  return och


def add_ct(bc, ct):
  bc.cts.append(ct)

def get_cts(bc):
  return bc.cts


def set_used(bc, us):
  #assert isinstance(bc, block.Block)
  #assert type(us) is bool
  bc.used = us
  # ----------------------------------------------------------------------

def used(bc):
  #assert isinstance(bc, block.Block)
  return bc.used
  # ----------------------------------------------------------------------
 

def bbox(BCS):
  B = None
  for bc in BCS:
    B = rn.box_join(B, path.bbox(bc.OPHS))
  assert B != None
  return B
  # ----------------------------------------------------------------------


def moves(bc):
  MVS = []
  for ich in range(nchoices(bc)):
    oph = choice(bc,ich)
    for ich in range(path.nelems(oph)):
      omv = path.elem(oph,ich)
      mv, dr = move.unpack(omv)
      MVS.append(mv)
  MVS = list(set(MVS))
  return MVS
  # ----------------------------------------------------------------------
  

def find_choice_with_move(bc, omv):
  for ich in range(nchoices(bc)):
    oph = choice(bc, ich)
    if path.find(oph, omv) != None:
      return ich
  return None
  #----------------------------------------------------------------------

def find_block_with_move(BCS, omv):
  nbc = len(BCS)
  for ich in range(nbc):
    bck = BCS[ich]
    if find_choice_with_move(bck, omv) != None:
      return ich
  return None


def min_extime(bc):
  #assert isinstance(bc, block.Block)
  n = len(bc.OPHS)
  mex = +inf
  for k in range(n):
    ophk = bc.OPHS[k]
    texk = path.extime(ophk)
    if texk < mex: mex = texk
  return mex