from qiskit import ClassicalRegister, QuantumRegister
from qiskit import QuantumCircuit, execute

from qiskit import register

#import Qconfig and set APIToken and API url
import sys, getpass
try:
    sys.path.append("../../") # go to parent dir
    import Qconfig
    qx_config = {
        "APItoken": Qconfig.APItoken,
        "url": Qconfig.config['url']}
    print('Qconfig loaded from %s.' % Qconfig.__file__)
except:
    APItoken = getpass.getpass('Please input your token and hit enter: ')
    qx_config = {
        "APItoken": APItoken,
        "url":"https://quantumexperience.ng.bluemix.net/api"}
    print('Qconfig.py not found in qiskit-tutorial directory; Qconfig loaded using user input.')
    
register(qx_config['APItoken'], qx_config['url'])

from battleships_engine import *

title_screen()

device = ask_for_device()

from qiskit import get_backend
backend = get_backend(device)

shipPos = ask_for_ships()

# the game variable will be set to False once the game is over
game = True

# the variable bombs[X][Y] will hold the number of times position Y has been bombed by player X+1
bomb = [ [0]*5 for _ in range(2)] # all values are initialized to zero

# set the number of samples used for statistics
shots = 1024

# the variable grid[player] will hold the results for the grid of each player
grid = [{},{}]

while (game):
    
    # ask both players where they want to bomb, and update the list of bombings so far
    bomb = ask_for_bombs( bomb )
    
    # now we create and run the quantum programs that implement this on the grid for each player
    qc = []
    for player in range(2):
        
        # now to set up the quantum program to simulate the grid for this player
        
        # set up registers and program
        q = QuantumRegister(5)
        c = ClassicalRegister(5)
        qc.append( QuantumCircuit(q, c) )
        
        # add the bombs (of the opposing player)
        for position in range(5):
            # add as many bombs as have been placed at this position
            for n in range( bomb[(player+1)%2][position] ):
                # the effectiveness of the bomb
                # (which means the quantum operation we apply)
                # depends on which ship it is
                for ship in [0,1,2]:
                    if ( position == shipPos[player][ship] ):
                        frac = 1/(ship+1)
                        # add this fraction of a NOT to the QASM
                        qc[player].u3(frac * math.pi, 0.0, 0.0, q[position])
                                        
        # Finally, measure them
        for position in range(5):
            qc[player].measure(q[position], c[position])

    # compile and run the quantum program
    job = execute(qc, backend, shots=shots)
    if device=='ibmqx4':
        print("\nWe've now get submitted the job to the quantum computer to see what happens to the ships of each player\n(it might take a while).\n")
    else:
        print("\nWe've now get submitted the job to the simulator to see what happens to the ships of each player.\n")
    # and extract data
    for player in range(2):
        grid[player] = job.result().get_counts(qc[player])
    
    game = display_grid ( grid, shipPos, shots )
        