# %matplotlib inline
# Importing standard Qiskit libraries and configuring account
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute, Aer, IBMQ
from qiskit.compiler import transpile, assemble
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from datetime import datetime
# import math
# Loading your IBM Q account(s)
# IBMQ.load_account()

backend = Aer.get_backend("qasm_simulator")

# global n_reg
# global m_reg
# global scratch_a
# global class_reg
# global backend
# global qc
# global test_timestamp

# def before_tests():
global n_reg # = QuantumRegister(6, 'n')
global scratch_a
global class_reg # = ClassicalRegister(6, 'y')

global qc # = QuantumCircuit(n_reg, m_reg, scratch_a, class_reg)

test_timestamp = datetime.now()

from ArithmaticFunctions import *

def setup_each_addition():
    n_reg = QuantumRegister(6, 'n')
    m_reg = QuantumRegister(6, 'm')
    scratch_a = QuantumRegister(6, 'sca')
    class_reg = ClassicalRegister(6, 'y')
    qc = QuantumCircuit(n_reg, m_reg, scratch_a, class_reg)
    
    return {'n_reg': n_reg, 'm_reg': m_reg, 'scratch_a': scratch_a, 'class_reg': class_reg, 'qc': qc }

def get_results_of_last_test():
#     for bit in range(len(n_reg)):
#         qc.measure(n_reg[bit], class_reg[bit])

    simulate = execute(qc, backend=backend, shots=1024).result()
    return simulate.get_counts()

def verify_results(expected):
    
    if [expected] == list(results.keys()):
        print("PASSING - ", test_timestamp)
    else:
        print("FAILING - ", test_timestamp)
        print(f'Got - {results}')
    



tc = setup_each_addition()
qc = tc['qc']

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('000000')

tc = setup_each_addition()
qc = tc['qc']

qc.x(tc['n_reg'][0])

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('111111')

tc = setup_each_addition()
qc = tc['qc']

qc.x(tc['n_reg'][2])

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('111100')

tc = setup_each_addition()
qc = tc['qc']

qc.x(tc['n_reg'][2])
qc.x(tc['n_reg'][3])
qc.x(tc['n_reg'][4])
qc.x(tc['n_reg'][5])

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('000100')

tc = setup_each_addition()
qc = tc['qc']

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('000000')

tc = setup_each_addition()
qc = tc['qc']

qc.x(tc['n_reg'][0])
qc.x(tc['n_reg'][1])
qc.x(tc['n_reg'][2])
qc.x(tc['n_reg'][3])
qc.x(tc['n_reg'][4])

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('100001')

tc = setup_each_addition()
qc = tc['qc']

twos_complement(tc['qc'], tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])
results = get_results_of_last_test()
verify_results('100001')

tc = setup_each_addition()
qc = tc['qc']
qc.x(tc['m_reg'][0])
qc.barrier()

twos_complement(qc, tc['n_reg'], tc['scratch_a'])
add_to_b_in_place(qc, tc['m_reg'], tc['n_reg'], tc['scratch_a'])
twos_complement(qc, tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])

results = get_results_of_last_test()
verify_results('111111')

tc = setup_each_addition()
qc = tc['qc']
qc.x(tc['m_reg'][0])
qc.x(tc['m_reg'][1])
qc.x(tc['m_reg'][2])
qc.x(tc['m_reg'][3])
qc.x(tc['m_reg'][4])
qc.x(tc['m_reg'][5])

qc.barrier()

twos_complement(qc, tc['n_reg'], tc['scratch_a'])
add_to_b_in_place(qc, tc['m_reg'], tc['n_reg'], tc['scratch_a'])
twos_complement(qc, tc['n_reg'], tc['scratch_a'])
qc.measure(tc['n_reg'], tc['class_reg'])

results = get_results_of_last_test()
verify_results('111111')

