import numpy as np
import math
import cv2
import sqlite3 as sql
import time
from tkinter import *
from tkinter import messagebox
import os.path as op
import os

path="C:\\Users\\asus\\Desktop\\facedatabase.npy"
if(not op.exists(path)):
    f=open(path,'w+')
    f.close()
    training_data=[]
else:
    if(os.stat(path).st_size==0):
        training_data=[]
    else:
        train_data=np.load(path)
        training_data=train_data.tolist()

top = Tk()
top.title("Staff Tracking Automation")
top.geometry("250x120")
top.resizable("False","False")

def Yeni_Kayit():

    top1=Toplevel()
    top1.geometry("500x500")
    top1.resizable(False,False)
    global e1,e2,e3,e4
    l1=Label(top1,text="Name:",)
    l1.place(x=100,y=50)
    e1=Entry(top1,bd=5,font=8)
    e1.place(x=200,y=50)
    l2 = Label(top1, text="Surname:",)
    l2.place(x=100, y=100)
    e2 = Entry(top1, bd=5, font=8)
    e2.place(x=200, y=100)
    l3 = Label(top1, text="Department:",)
    l3.place(x=100, y=150)
    e3 = Entry(top1, bd=5, font=8)
    e3.place(x=200, y=150)
    l4 = Label(top1, text="Position:",)
    l4.place(x=100, y=200)
    e4 = Entry(top1, bd=5, font=8)
    e4.place(x=200, y=200)
    B1=Button(top1,text="Kayda Başla",fg="white",bg="navyblue",command=kayda_basla)
    B1.place(x=200,y=300)


def temizle():
    vt=sql.connect("C:\\Users\\asus\\Desktop\\bitirme.db")
    im=vt.cursor()
    im.execute("""delete from Operations""")
    im.execute("""delete from Employee""")
    vt.commit()
    vt.close()

def kayda_basla():
    global training_data,MeanVector,CovarianceMatrixTEigenVectors,WeigthMatrix
    face_cascade = cv2.CascadeClassifier('C:\\Users\\asus\\Desktop\\haarcascades\\haarcascade_frontalface_default.xml')
    cap = cv2.VideoCapture(0)
    count=10
    temp=0
    while True:
        ret, frame = cap.read()
        sec = time.gmtime().tm_sec
        faces = face_cascade.detectMultiScale(frame, 1.2, 3)
        for (x, y, w, h) in faces:
            gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            pix = gray[y:y + 140, x:x + 140]  # y+h a göreymis
            #print("x: {}\ny: {}\nw: {}\nh: {}".format(x,y,np.array(pix).shape,h))
            if(sec%2==1):
                temp=0
            if(count>0 and sec%2==0 and temp%2==0 ):
                temp = sec + 1
                I1=np.array(pix).flatten()
                training_data.append(I1)
                count-=1


        cv2.imshow("Video", frame)
        if (cv2.waitKey(1) and 0xFF == ord('q')):
            break
        elif(count==0):
            messagebox.showinfo("Uyarı","Kayıt Tamamlandı")
            break

    cap.release()
    cv2.destroyAllWindows()

    sum = 0
    mean = 0
    MeanVector = []

    training_data = np.array(training_data)
    training_data = training_data.transpose()
    # print(training_data)
    for i in training_data:
        for j in range(0, len(i), 1):
            sum += i[j]
        mean = sum / len(i)
        MeanVector.append(mean)
        sum = 0
        mean = 0

    # A matrisinin bulunması
    AMatrix = []
    dizi = []
    training_dataT = training_data.transpose()
    for i in training_dataT:
        for j in range(0, len(i), 1):
            eleman = i[j] - MeanVector[j]
            dizi.insert(j, eleman)
        dizi1 = np.array(dizi)
        AMatrix.append(dizi1)
        dizi.clear()  # copy yapmazsak nereye koyduysak ordaki elemanlarda silinir saçma ama öle

    AMatrix = np.array(AMatrix)
    AMatrix = AMatrix.transpose()
     # N2*M boyutunda

    CovarianceMatrix = np.matmul(AMatrix.transpose(), AMatrix)
    print(CovarianceMatrix.shape)  # M*M boyutunda
    #print(CovarianceMatrix)
    # cov matrisinin özdeğerleri matris ile çarpılarak özdeğerlerin özvektörler ile çarpımı bulunur

    matrix = np.linalg.eig(CovarianceMatrix)
    EigenValues = matrix[0]
    EigenVectors = matrix[1]
    CovarianceMatrixTEigenVectors = np.matmul(AMatrix, EigenVectors)# N2*M her görüntünün özvektörü
    CMat = CovarianceMatrixTEigenVectors.T
    WeigthMatrix=[]
    for i in CMat:
        WeigthMatrix.append(np.matmul(i, AMatrix))
    WeigthMatrix = np.array(WeigthMatrix).T

    sayi=len(WeigthMatrix)
    
    if(sayi%10!=0):
        print("hata resim sayisi yanlıs sayi = {}".format(sayi))
        return False
    else:
        person=(sayi/10)-1;

    name1 = e1.get()
    surname1 = e2.get()
    department1 = e3.get()
    position1 = e4.get()

    vt = sql.connect("C:\\Users\\asus\\Desktop\\bitirme.db")
    im = vt.cursor()
    im.execute(""" insert into Employee values(?,?,?,?,?)""",(str(person),name1.capitalize(),surname1.capitalize(),department1.capitalize(),position1.capitalize()))#frame ler den gelecek veriler koyulacak
    vt.commit()
    vt.close()
    training_data=training_data.transpose()
    np.save("C:\\Users\\asus\\Desktop\\facedatabase.npy",training_data)
    training_data=training_data.tolist()

def compile_reg():
    global training_data, MeanVector, CovarianceMatrixTEigenVectors, WeigthMatrix
    sum = 0
    mean = 0
    MeanVector = []
    training_data = np.array(training_data)
    training_data = training_data.transpose()
    # print(training_data)
    for i in training_data:
        for j in range(0, len(i), 1):
            sum += i[j]
        mean = sum / len(i)
        MeanVector.append(mean)
        sum = 0
        mean = 0

    # A matrisinin bulunması
    AMatrix = []
    dizi = []
    training_dataT = training_data.transpose()
    for i in training_dataT:
        for j in range(0, len(i), 1):
            eleman = i[j] - MeanVector[j]
            dizi.insert(j, eleman)
        dizi1 = np.array(dizi)
        AMatrix.append(dizi1)
        dizi.clear()  # copy yapmazsak nereye koyduysak ordaki elemanlarda silinir saçma ama öle

    AMatrix = np.array(AMatrix)
    AMatrix = AMatrix.transpose()
    # N2*M boyutunda

    CovarianceMatrix = np.matmul(AMatrix.transpose(), AMatrix)
    print(CovarianceMatrix.shape)  # M*M boyutunda
    # print(CovarianceMatrix)
    # cov matrisinin özdeğerleri matris ile çarpılarak özdeğerlerin özvektörler ile çarpımı bulunur

    matrix = np.linalg.eig(CovarianceMatrix)
    EigenValues = matrix[0]
    EigenVectors = matrix[1]


    CovarianceMatrixTEigenVectors = np.matmul(AMatrix, EigenVectors)  # N2*M her görüntünün özvektörü
    CMat = CovarianceMatrixTEigenVectors.T

    WeigthMatrix = []
    for i in CMat:
        WeigthMatrix.append(np.matmul(i, AMatrix))
    WeigthMatrix = np.array(WeigthMatrix).T


def Face_Recognition():
    face_cascade = cv2.CascadeClassifier('C:\\Users\\asus\\Desktop\\haarcascades\\haarcascade_frontalface_default.xml')
    cap = cv2.VideoCapture(0)


    count = 75
    distance = 0
    while True:
        ret, frame = cap.read()

        faces = face_cascade.detectMultiScale(frame, 1.2, 3)
        for (x, y, w, h) in faces:
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
            pix = gray[y:y + 140, x:x + 140]  # y+h a göreymis
            if (count==0):
               if(w>70 and h >70):
                test_data = np.array(pix).flatten()
                FiData = test_data - MeanVector
                TestWeigthMatrix = np.matmul(CovarianceMatrixTEigenVectors.T, FiData)
                liste=[]
                optime = time.asctime()
                strop1 = "Giriş Yaptı"
                strop2 = "Çıkış Yaptı"

                sorguindex=0
                kisi=0
                vall=0#kişi denetimi

                for i in WeigthMatrix:
                    for j in range(0, len(i), 1):
                        distance += math.pow(math.ceil((TestWeigthMatrix[j] - i[j])), 2)
                    distance = math.sqrt(distance)
                    liste.append(int(distance)/10**6)
                    distance=0
                    if len(liste) %10 == 0:
                        deger=np.mean(liste[kisi*10:(kisi+1)*10:1])
                        print(deger)
                        if(deger>29*(len(WeigthMatrix)/10)):
                            vall+=1
                        kisi+=1

                if(vall==len(WeigthMatrix)/10):
                    print("Kisi Bulunamadı\n")
                    count=75
                    break
                else:
                    sorguindex=liste.index(min(liste))

                if (sorguindex % 10 != 0):
                    mod = sorguindex % 10
                    sorguindex = (sorguindex - mod) / 10
                else:
                    sorguindex /= 10

                sorguindex = int(sorguindex)

                vt = sql.connect("C:\\Users\\asus\\Desktop\\bitirme.db")
                im = vt.cursor()
                im.execute("""SELECT name,surname,department,position from Employee where location = ? """,
                           (str(sorguindex)))
                sqldata = im.fetchall()
                if (sqldata):  # gelen verileri al ikinci veritabanına yaz
                    name = sqldata[0][0]
                    surname = sqldata[0][1]
                    department = sqldata[0][2]
                    position = sqldata[0][3]
                    im.execute(""" select operation from Operations where name = ? and surname = ? and department = ? and position = ? order by optime desc limit 1""",(name,surname,department,position))
                    opdata=im.fetchone()
                    if(opdata):

                        if(opdata[0]==strop1):
                            im.execute("""insert into Operations values (?,?,?,?,?,?)""",
                                          (name.capitalize(), surname.capitalize(), department.capitalize(), position.capitalize(), optime, strop2))
                            print(
                                "İsim: {}\tSoyisim: {}\tDepartment: {}\tPosition: {}\tİşlemTarihi: {}\tSonİşlem: {}".format(
                                    name.upper(), surname.upper(), department.upper(),
                                    position.upper(), optime, strop2))
                        elif(opdata[0]==strop2):
                            im.execute("""insert into Operations values (?,?,?,?,?,?)""",
                            (name.capitalize(), surname.capitalize(), department.capitalize(), position.capitalize(), optime, strop1))
                            print(
                                "İsim: {}\tSoyisim: {}\tDepartment: {}\tPosition: {}\tİşlemTarihi: {}\tSonİşlem: {}".format(
                                name.upper(), surname.upper(), department.upper(),
                                position.upper(), optime, strop1))

                    else:

                        im.execute("""insert into Operations values (?,?,?,?,?,?)""",
                                   (name.capitalize(), surname.capitalize(), department.capitalize(), position.capitalize(), optime, strop1))
                        print(
                            "İsim: {}\tSoyisim: {}\tDepartment: {}\tPosition: {}\tİşlemTarihi: {}\tSonİşlem: {}".format(
                                name.upper(), surname.upper(), department.upper(),
                                position.upper(), optime, strop1))
                count=75
                vt.commit()
            else:
                count-=1

        cv2.imshow("Video", frame)

        if (cv2.waitKey(1) and 0xFF == ord('q')):
            break

    cap.release()
    cv2.destroyAllWindows()

    vt.close()


kayitbuton = Button(top, text="Yeni Kayıt", bg="red", fg="white", command=Yeni_Kayit)
kayitbuton.place(x=20, y=30)
kamerabuton=Button(top,text="Personel Takip Sistemi",bg="green",fg="white",command=Face_Recognition)
kamerabuton.place(x=100,y=30)
clsbuton=Button(top,text="Kayıtları Temizle",bg="cyan",fg="red",command=temizle)
clsbuton.place(x=20,y=70)
cmpbutton=Button(top,text="Compile Database",bg="brown",fg="white",command=compile_reg)
cmpbutton.place(x=120,y=70)
top.mainloop()


