import sys
#add local qiskit-terra/test/python path here to import transpiler._dummy_passes
#test_path='<enter path here>'
sys.path.append(test_path)

from transpiler import test_pass_scheduler
from qiskit import QuantumCircuit,QuantumRegister
from qiskit.transpiler import PassManager
from qiskit.transpiler.runningpassmanager import ConditionalController,DoWhileController
from transpiler._dummy_passes import (
    PassA_TP_NR_NP,
    PassB_TP_RA_PA,
    PassC_TP_RA_PA,
    PassD_TP_NR_NP,
    PassE_AP_NR_NP,
    PassF_reduce_dag_property,
    PassI_Bad_AP,
    PassJ_Bad_NoReturn,
    PassK_check_fixed_point_property,
    PassM_AP_NR_NP,
)

from transpiler.test_pass_scheduler import SchedulerTestCase

def show_run(passmanager,circuit):
    myScheduler=SchedulerTestCase()

    with myScheduler.assertLogs("LocalLogger", level="INFO") as cm:
        out = passmanager.run(circuit)
    return [record.message for record in cm.records]

#Creating a nested ConditionalController

#Defining PassManager and circuit
passmanager=PassManager()
circuit = QuantumCircuit(QuantumRegister(1))

#Runs PassA_TP_NR_NP if property_set["property"] is True
#Passes like PassA_TP_NR_NP are just test passes used in the test suite

nested_conditional=[ConditionalController(
                    [PassA_TP_NR_NP()], 
                    condition=lambda property_set: property_set["property"])]

passmanager.append([PassE_AP_NR_NP(True)] +
                   nested_conditional)

show_run(passmanager,circuit)



#Nesting a ConditionalController inside of a loop

#Defining PassManager and circuit
passmanager=PassManager()
circuit = QuantumCircuit(QuantumRegister(1))

#Runs PassA_TP_NR_NP if property_set["property"] is True

nested_conditional=[ConditionalController(
                    [PassA_TP_NR_NP()], 
                    condition=lambda property_set: property_set["property"])]

passmanager.append([PassK_check_fixed_point_property(), PassE_AP_NR_NP(True)] 
                   + nested_conditional 
                   + [PassF_reduce_dag_property()],
                   do_while=lambda property_set: not property_set["property_fixed_point"])

show_run(passmanager,circuit)

#Nesting ConditionalControllers more than one level

passmanager=PassManager()
circuit = QuantumCircuit(QuantumRegister(1))

nested_level3=ConditionalController([PassC_TP_RA_PA()], condition=lambda property_set: property_set["property"])
nested_level2=ConditionalController([PassF_reduce_dag_property(),nested_level3],condition=lambda property_set: property_set["property"])
nested_level1=[ConditionalController([PassA_TP_NR_NP(),nested_level2], condition=lambda property_set: property_set["property"])]


passmanager.append([PassE_AP_NR_NP(True)] 
                    + nested_level1)
show_run(passmanager,circuit)

#Multiple nested ConditionalControllers on the same level
passmanager=PassManager()
circuit = QuantumCircuit(QuantumRegister(1))

nested_conditional1=[ConditionalController([PassB_TP_RA_PA()], condition=lambda property_set: property_set["property"])]
nested_conditional2=[ConditionalController([PassC_TP_RA_PA()], condition=lambda property_set: property_set["property"])]
nested_conditional3=[ConditionalController([PassD_TP_NR_NP()], condition=lambda property_set: property_set["property"])]


passmanager.append([PassE_AP_NR_NP(True)]
                    + nested_conditional1 
                    + [PassE_AP_NR_NP(False)]
                    + nested_conditional2
                    + [PassE_AP_NR_NP(True)]
                    + nested_conditional3)

show_run(passmanager,circuit)           

#Nested DoWhileController
passmanager=PassManager()
circuit = QuantumCircuit(QuantumRegister(1))

nested_do_while = [DoWhileController([PassK_check_fixed_point_property(),PassF_reduce_dag_property()],
                    do_while=lambda property_set: not property_set["property_fixed_point"])]

passmanager.append([PassD_TP_NR_NP()]
                    + nested_do_while
                    + [PassD_TP_NR_NP()])

show_run(passmanager,circuit)

from qiskit.circuit.library import QuantumVolume
from qiskit import *


from qiskit.test.mock import FakeBelem
qcomp = FakeBelem()

qv_circuit=QuantumVolume(3)
qv_circuit.draw()

from IPython.display import display
from qiskit.converters import dag_to_circuit
from qiskit.transpiler import TransformationPass
from qiskit.converters import dag_to_circuit


def my_callback(pass_,dag, time, property_set, count):   
    circuit = dag_to_circuit(dag)
    print(pass_.name())
    #display(circuit.draw(output='mpl'))
    circuit = dag_to_circuit(dag)

transpile(qv_circuit,backend=qcomp, optimization_level=3,callback=my_callback,translation_method='synthesis').draw(output='mpl')



