#!/usr/bin/env python
import argparse
# use QSCircuit libreary
from QSCircuit import QSCircuit

_flag_verbose = False
def verbose(arg):
	# simple verbose printing function
    if _flag_verbose: print (arg)

def main(args, function):
	# starting input dimension of qubit-register for custom circuits
    starting_dim_reg = args.reg_size[0]-1 if args.reg_size else 0

    # intialize class with starting input dimension of qubit-register
    qsCircuit = QSCircuit.QSCircuit(starting_dim_reg)

    # set boolean function to convert
    parsed_input = qsCircuit.set_input(function)
    verbose("qsCircuit.input: "+str(parsed_input))

	# optimize compiled circuit during conversion if required
    if args.optimize:
    	# set
        qsCircuit.setOptimize(True)
    else:
        qsCircuit.setOptimize(False)

    # convert input function into quanistic circuit
    converted_circuit = qsCircuit.convert()

    if args.print_circuit:
    	# print quantum circuit scheme
        qsCircuit.print_circuit()

	# return circuit as a List
    circuit = qsCircuit.asList()
    verbose('Register Size: ' + str(qsCircuit.get_regiser_size()))
    verbose('N. operations: ' + str(len(circuit)))
    verbose('Result Operation: ' + qsCircuit.asString())
    print('QScript Circuit: ' + qsCircuit.asQScript())

parser = argparse.ArgumentParser(description="Boolean function converter into QScript gates. Input funciton must be express in C-styles '~, &, |, ^'. ")
parser.add_argument("-r", "--register-size", help="starting n-qubit register", type=int, nargs=1, default=0, dest="reg_size")
parser.add_argument("function", help="function that describe classical circuit ", nargs=1)
parser.add_argument("-v", "--verbose", help="verbose log", action='store_true')
parser.add_argument("-o", "--optimize", help="optimize quantum circuit", action='store_true')
parser.add_argument("-p", "--print_circuit", help="print quantum circuit scheme", action='store_true')

args = parser.parse_args()
if (args.verbose): _flag_verbose = True

main(args, args.function[0])

# Exemples of linear boolean functions:
# "(x2 & x3 & x4 ) ^ (x2 & x3 & x5 ) ^ (x1 & x2 ) ^ (x3 & x4)  ^ (x4 & x5 ) ^ x3)"
# "(((x0 & x1) ^ (x0 & x2)) ^ (x1 &  x2))"
# "x0 & x1 & x2 & x4 ^ x5"
