# needed qiskit library
from qiskit import *
%matplotlib inline

# the channel library providing the class Channel handling the communication
from channel_class import Channel

#Bob needs to know the number of qubits, n_master: number of Alice qubits, n_slave: number of Bobs qubits
n_master = 2 
n_channel = 2
n_slave = 1

#initialise the Quantum Channel, Bobs port is 5001, Alice port is 5000
bob_channel = Channel(myport = 5001, remote_port = 5000)

#initialise Bobs circuit
circ_bob = QuantumCircuit(n_master + n_channel + n_slave)

#Bob recieves the qubits from Alice and needs to give his computations up to then into the function
#the function returns the circuit on which Bob continues to operate and an offset he has to add all the time
circ_bob, offset = bob_channel.receive(circ_bob)

# Bob does the controlled operations on his qubit (which is 0+offset) 
circ_bob.cx(1+offset,2+offset)
circ_bob.cz(0+offset,2+offset)

# Bob undoes the rotations Alice did to check, whether the states are indeed the same
circ_bob.rx(-0.1,2 + offset)
circ_bob.ry(-0.94,2 + offset)
circ_bob.rz(-0.54,2 + offset)
circ_bob.rx(-0.234,2 + offset)

# The complete Circuit
circ_bob.draw(output='mpl',filename='teleport_bob.png')

# Bob measure his qubit, if the teleportation worked, he undoes exactly what Alice did
meas = QuantumCircuit(5,1)
meas.barrier(range(5))
meas.measure([4],range(1))
qc = circ_bob + meas

# The whole teleportation protocol is simulated
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc,backend_sim,shots=1024)
result_sim = job_sim.result()
counts = result_sim.get_counts(qc)

# if Bob undid all of Alice's steps correctly, the final state of his qubit is |0>
print(counts)

