import time, os, logging, warnings
from qiskit_optimization.algorithms import CplexOptimizer
warnings.filterwarnings("ignore", category=DeprecationWarning)
from qiskit.optimization.algorithms.optimization_algorithm import OptimizationResultStatus
from dwave.system import DWaveCliqueSampler
from utilities.helpers import create_dwave_meo, create_quadratic_programs_from_paths

TEST_DIR = 'TEST_DATA' + "/" + time.strftime("%d_%m_%Y") + "/DENSE/"
RES_DIR = 'RESULTS' + "/" + time.strftime("%d_%m_%Y") + "/DENSE/"
os.makedirs(RES_DIR, exist_ok=True)
TEST_DIR

# select linear programs to solve
qps = create_quadratic_programs_from_paths(TEST_DIR, True)
# init Optimizers
cplex = CplexOptimizer()
dwave = create_dwave_meo(DWaveCliqueSampler(), num_reads=4096)
prelabel = "clique_dense_"

logger = logging.getLogger()
logger.setLevel(logging.INFO)
warnings.filterwarnings("ignore", category=DeprecationWarning)

count_fail_dwave = 0

for qp_name, qp in qps.items() :
    
    print(qp_name)
    print("number of qubits: ", qp.get_num_vars())
    output_file_handler = logging.FileHandler(filename=RES_DIR + qp.name + ".log")
    logger.addHandler(output_file_handler)

    # set problem label
    dwave.min_eigen_solver.sampler.set_label(prelabel + qp_name + "_" + str(qp.get_num_vars()))

    with open(RES_DIR + qp.name + '.res', 'w') as file:
        file.write(str("Start " + qp.name + "\n " + str(qp.get_num_vars()) + " qubits needed"))  
        file.write("\n DWave Quantum: \n")
        logger.info("\n DWave Quantum: \n ")
        try:
            res_classic = cplex.solve(qp)
            res_quantum = dwave.solve(qp)
            problem_id = str(res_quantum.min_eigen_solver_result.sampleset.info['problem_id'])
            logger.info("\n problem id " + problem_id)
            file.write("\n problem id: " + problem_id)
            
            if res_quantum.status != OptimizationResultStatus.SUCCESS:
                print("Dwave quantum solver found no solution.")
                file.write("\n No solution found with DWave Quantum Solver \n")
                count_fail_dwave = count_fail_dwave + 1
                if count_fail_dwave == 3:
                    file.write("\n Stop testing DWave Quantum Solver \n")
                    break
            else:
                print("Dwave Quantum successful!")
                count_fail_dwave = 0
                if res_quantum.fval == res_classic.fval:
                    file.write("\n DWave quantum solver found optimal solution\n")
                else:
                    print("\n optimal value Dwave quantum "+str(res_quantum.fval) \
                                           + "  ,  cplex:"+ str(res_classic.fval))
                    file.write("\n DWave quantum solver:\n")
                    file.write(str(res_quantum))
                    file.write("\n CPLEX:\n")
                    file.write(str(res_classic))

        except Exception as ex:
            print(qp_name, " ", type(ex).__name__, " : ", ex)
            file.write("\n Cplex or DWave solver produced an exception:\n")
            file.write(str(ex))
            count_fail_dwave = count_fail_dwave + 1
            if count_fail_dwave == 3:
                file.write("\n Stop testing because of Exception! \n")
                break
                
    logger.removeHandler(output_file_handler)