#!/usr/bin/env python3

import numpy as np
from . import kSAT
from tqdm import tqdm
import math

__VERTEX_WEIGHT__ = 1
__EDGE_WEIGHT__ = -2

def WMISdictQUBO(kSATInstance):
    quboInstance = {}
    
    for clauseIndex in tqdm(range(kSATInstance.getNumberOfClauses())):
        clause = kSATInstance.getClause(clauseIndex)
        
        # build triangles
        for varIndexInClause in range(len(clause)):
            label = kSATInstance.getLableOfBinding(clauseIndex,
                                                   clause[varIndexInClause])
            quboInstance[(label, label)] = __VERTEX_WEIGHT__
            
            for i in range(varIndexInClause + 1, len(clause)):
                targetLabel = kSATInstance.getLableOfBinding(clauseIndex,
                                                             clause[i])
                
                quboInstance[(label, targetLabel)] = __EDGE_WEIGHT__
        
    # connect conflicts
    for conflict in kSATInstance.getConflicts():
        quboInstance[(conflict[0], conflict[1])] = __EDGE_WEIGHT__
    
    return quboInstance
    
class QuboWriter:
    def __init__(self, qubo):
        self.__labelIndexDict = {}
        self.__qubo = qubo
        
        self.__initLabelIndexDict(self.__qubo)
        
        print(self.__labelIndexDict)
    
    def __initLabelIndexDict(self, qubo):
        indexCount = 0
        
        for coupler in qubo:
            
            label1 = coupler[0]
            label2 = coupler[1]
            
            if label1 not in self.__labelIndexDict:
                self.__labelIndexDict[label1] = indexCount
                indexCount += 1
            
            if label2 not in self.__labelIndexDict:
                self.__labelIndexDict[label2] = indexCount
                indexCount += 1
    
    def write(self, filePath):
        quboFile = open(filePath, "w")
    
        self.__writeQuboFileHeader(quboFile)
        self.__writeQuboFileNodes(quboFile)
        self.__writeQuboFileCouplers(quboFile)
    
        quboFile.close()
    
    def __writeQuboFileHeader(self, quboFile):
        numberOfNodes = len(self.__labelIndexDict)
        numberOfCouplers = len(self.__qubo) - numberOfNodes
    
        quboFile.write("c\n")
        quboFile.write("c this is a generated qubo file\n")
        quboFile.write("c\n")
    
        quboFile.write("p qubo 0 %d %d %d\n" %(numberOfNodes,
                                               numberOfNodes,
                                               numberOfCouplers))
                                               
    def __writeQuboFileNodes(self, quboFile):
        for label in self.__labelIndexDict:
            self.__writeCoupler(quboFile, (label, label))
            
    def __writeCoupler(self, quboFile, coupler):
            indices = self.__getNodeIndicesFromCoupler(coupler)
    
            quboFile.write("%d %d  %d\n" % (indices[0],
                                            indices[1],
                                            self.__qubo[coupler]))

    def __getNodeIndicesFromCoupler(self, coupler):
        index1 = self.__labelIndexDict[coupler[0]]
        index2 = self.__labelIndexDict[coupler[1]]
        
        if index1 <= index2:
            return [index1, index2]
        else:
            return [index2, index1]
            
    def __writeQuboFileCouplers(self, quboFile):
        for coupler in self.__qubo:
            if coupler[0] != coupler[1]:
                self.__writeCoupler(quboFile, coupler)

