import serial
import binascii
import math
import mariadb


# aktuell ist es so programmiert, dass es annimmt, dass in kg gemessen wird (andere Einheiten liefern also flasche Ergebnisse)
# das was man noch dazuprogrammieren kann, ist wenn mehrere Teile auf der Waage liegen, ob dann die Typen noch immer erkannt werden




db_config = {
    'user': 'dbUser',
    'password': 'dbPassword',
    'host': 'localhost',
    'database': 'projectGeislinger',
    'port': 3306  # Standard port for MariaDB
}

# Establishing the connection
conn = mariadb.connect(**db_config)
# Create a cursor to execute queries
cursor = conn.cursor()

# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)

waageEingeschwungen = False

def getDataOfArticleType(allArticles, articleType):
    # die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück

    for i in allArticles:
        if i[1] == articleType:
            return i

    return -1

def getDataOfArticleNotType(allArticles, articleType):
    # die Funktion geht die Liste mit allen Artikeln durch und gibt jene Einträge, welche nicht mit dem "articleTypen" übereinstimmt zurück
    returnMatrix = []

    for i in allArticles:
        if i[1] != articleType:
            returnMatrix.append(i)

    return returnMatrix





def wahrscheinlichkeitsDichte(x,mue, var):
    # in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet
    standardabweichung = var**0.5

    result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)

    return result


def generateArticleProbabilities(articleType, allArticles, n, x, numberOfOtherTypes, measuredWeight):
    # es fehtl noch eine Datavariable, welche die Daten der Datenbank beinhaltet

    # articleType ... die Artikeltype, welche erwartet wird (also für welche n+x überprüft wird)
    # n ... Anzahl der Artikel, welche laut dem Auftrag vorhanden sein sollten
    # x ... Anzahl der Artikel vom Artikeltypen des Auftrages, welche über der Anzahl n noch überprüft werden sollen
    # numberofOtherTypes ... Anzahl an Artikeln, welch von anderen Typen überprüft werden sollen
    # measuredWeight ... das Gewicht, welches von der Waage gemessen wird

    # über alle Möglichkeiten drüberiterieren, die Wahrscheinlichkeitsdichte für diese berechnen und in einer Matrix speichern.

    # in der Folge werden die artikelbezogenen Daten in einer Matrix zusammengefasst 
    articleData = getDataOfArticleType(allArticles, articleType)
    if articleData == -1:
        return -1

    otherArticleData = getDataOfArticleNotType(allArticles, articleType)


    #print("AData: ", articleData)
    print("NArticleData: ", otherArticleData)

    #print(wahrscheinlichkeitsDichte(measuredWeight, articleData[1], articleData[2]))

   
    articleProbMatix = []

    for i in range(numberOfOtherTypes+1):
        for j in range(n+x):
            anzArtikelToCheck = j+1
            propDensity = wahrscheinlichkeitsDichte(measuredWeight*anzArtikelToCheck, articleData[2], articleData[3])
            print(propDensity)



    return 0




'''
def numberSmallerObjects(numberBiggerObjects, messungWaage, mue1,mue2, sigma2):
    for i in range(1,10000):
        #damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
        # eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
        if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:    
            print((messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1)

            if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
                return i
        else:
            return -1
'''


def main():

    
    print("connection is open: ", ser.is_open)
    print("port to which it is connected: ", ser.portstr)

    
    #an die Waage den Befehl senden, dass sie ausgelesen werden soll
    ser.write(b'getWeight\n')
    #ser.write(b'tare\n')
    serialString = ser.readline().decode('utf-8').rstrip()  #Auslesen des Serial-Strings/der Messung der Waage
    
    # wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
    lenString = len(serialString)-1
    if serialString[lenString] == "g" and serialString[lenString-1] == "k":
        print("ist eingeschwungen")
        waageEingeschwungen = True
    else:
        print("die Waage ist noch nicht eingeschwungen")
        waageEingeschwungen = False

    #aus dem String werden alle Zeichen, welche nicht zur Darstellung der Zahl benötigt werden entfernt
    intString = ""
    for i in serialString:
        if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
            intString = intString + i
    print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
    

    # wenn die Waage nicht eingeschwungen ist, dann soll auch nichts weiter gemacht werden
    if( waageEingeschwungen == True):

        # new SWL-Query
        sql_query = "SELECT * FROM projectGeislinger.Auftraege, projectGeislinger.Einzelteile where projectGeislinger.Auftraege.EinzelteilID = projectGeislinger.Einzelteile.id "
        # Execute the query
        cursor.execute(sql_query)
        # Fetch results
        auftragDaten = cursor.fetchall()
        # Display data
        print("Ausgabe der Daten der Datenbank:")
        for row in auftragDaten:
            print(row)


        # Define the SQL query
        sql_query = "SELECT * FROM projectGeislinger.Einzelteile"
        # Execute the query
        cursor.execute(sql_query)
        # Fetch results
        einzelteile = cursor.fetchall()
        # Display data
        print("Ausgabe der Daten der Datenbank:")
        for row in einzelteile:
            print(row)




        #print(einzelteile)

        #
        selectedRow = 0     #diese wird durch die GUI vorgegeben, oder automatische ausgewählt

        artikelBezeichnung = auftragDaten[selectedRow][5]
        
        # 10 Anzahl laut Auftrag, 3, Anzahl darüber, 1 Anzahl anderer Typ
        generateArticleProbabilities(artikelBezeichnung, einzelteile, 2, 0,1, float(intString))



    
    




    ser.close()
    print("connection is open: ", ser.is_open)






if __name__ == "__main__":
    main()



