import sys
import platform
import glob
import cv2
import os
from flask_cors import CORS
import jsonpickle
import numpy as np
import mysql.connector
from flask import Flask, request
from PIL import Image
from mysql.connector import Error   
from flask_apscheduler import APScheduler
import base64
from io import BytesIO


######
import matplotlib.pyplot as plt

import math
from scipy import ndimage
#####

print(cv2.__version__)



print(sys.version)
app = Flask(__name__)
CORS(app, supports_credentials=True, resources={r"/*": {"origins": "*"}}, headers=['Content-Type', 'Authorization'])
threshold = 40
kernel = np.ones((5, 5), np.uint8)
global status
status="NOT"
global isGoodFeatures
isGoodFeatures="GOOD"
orb = cv2.ORB_create(nfeatures=1000)
descriptor = cv2.xfeatures2d.BEBLID_create(0.75)


global images
images = []
global matchlist
matchlist = []
global ClassNames
ClassNames = []
global filelist
filelist= []
global name

APP_ROOT = os.path.dirname(os.path.abspath(__file__))   # refers to application_top
APP_STATIC = os.path.join(APP_ROOT, 'arhimaya/Headerimage')
#print(APP_STATIC)
for root, dirs, files in os.walk(APP_STATIC):
    for file in files:
        # append the file name to the list
        filelist.append(os.path.join(root, file))
#print(filelist)

for name in filelist:
    newPath = name.replace(os.sep, '/')
    # print(newPath)
    # print(name)
    print(newPath)
    imgCur = cv2.imread(newPath, 0)
    images.append(imgCur)
    # print(imgCur)
    ClassNames.append(os.path.splitext(newPath)[0] + os.path.splitext(newPath)[1])

#print(ClassNames)
@app.route('/VisionMaya')
def VisionMaya():
  return 'Welcome to VisionMaya 2.2 UPDATED AUTOSAVE TODAy'

@app.route('/blogs')
def blogs():
  return 'Welcome1 to The Blog App_Updated_BYTES'

@app.route('/blog/<int:id>')
def blog(id):
  return "The Blog id is {}".format(id)

@app.route('/selva')
def selva():
    global ClassNames
    classNames=["sankari","siva"]
    return jsonpickle.encode(ClassNames)





@app.route('/siva')
def siva():
    global filelist
    global name
    global images
    global ClassNames
    global matchlist
    
    filelist.clear()
    ClassNames.clear()
    filelist.clear()
    images.clear()
    matchlist.clear()

    #filelist = []
    #print(files)
    APP_ROOT = os.path.dirname(os.path.abspath(__file__))   # refers to application_top
    APP_STATIC = os.path.join(APP_ROOT, 'arhimaya/Headerimage')
    #for files in os.walk('APP_STATIC'):
        #for filename in files:
            #fname = os.path.join(dirpath, filename)
            #if fname.endswith('.jpg'):
                #print(fname)
    for root, dirs, files in os.walk(APP_STATIC):
        for file in files:
            # append the file name to the list
            filelist.append(os.path.join(root, file))
    #print(filelist)

    for name in filelist:
        newPath = name.replace(os.sep, '/')
        # print(newPath)
        # print(name)
        #print(newPath)
        imgCur = cv2.imread(newPath, 0)
        images.append(imgCur)
        # print(imgCur)
        ClassNames.append(os.path.splitext(newPath)[0] + os.path.splitext(newPath)[1])

    #siva="SANKARI"
    #for dirpath, dirs, files in os.walk('env'):
      #for filename in files:
        #fname = os.path.join(dirpath,filename)
        #siva=siva+'.'+fname
        #if fname.endswith('.py'):
          #print(fname)
          #siva=siva+"New"+fname
    return jsonpickle.encode(ClassNames)

#print(ClassNames)
def findDes(images):
    desList = []
    for img in images:
        #kp, des = orb.detectAndCompute(img, None)
        kp = orb.detect(img, None)
        kp, des = descriptor.compute(img, kp)
        desList.append(des)
    return desList


def findID(img, deslist):
    kp2 = orb.detect(img, None)
    kp2, des2 = descriptor.compute(img, kp2)
    #kp2, des2 = orb.detectAndCompute(img, None)
    #bf = cv2.BFMatcher()
    bf = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING)
    matchlist.clear()
    finalvalue = -1
    try:
        for des in deslist:
            matches = bf.knnMatch(des, des2, k=2)
            good = []
            matched1 = []
            matched2 = []
            nn_match_ratio = 0.8  # Nearest neighbor matching ratio
            
            for m, n in matches:
                if m.distance < nn_match_ratio * n.distance:
                #if n < len(matches) - 1 and n.distance < 0.7 * matches[n+1].distance:
                    good.append(des[m.queryIdx])
                    #matched1.append(kpts1[m.queryIdx])
                    #matched2.append(kpts2[m.trainIdx])
                    #print(len(matched1))
                    
            matchlist.append(len(good))
            
    except:
        pass
    if len(matchlist) != 0:
        if max(matchlist) > threshold:
            finalvalue = matchlist.index(max(matchlist))
    return finalvalue


@app.route('/')
def hello_world():
    return cv2.__version__

def variance_of_laplacian(image):
	# compute the Laplacian of the image and then return the focus
	# measure, which is simply the variance of the Laplacian
	return cv2.Laplacian(image, cv2.CV_64F).var()

@app.route('/post_json', methods=['POST'])
def image_check():
    # ----- SECTION 1 -----
    # File naming process for nameless base64 data.
    # We are using the timestamp as a file_name.
    from datetime import datetime
    dateTimeObj = datetime.now()
    file_name_for_base64_data = dateTimeObj.strftime("%d-%b-%Y--(%H-%M-%S)")
    '''
    content_type = request.headers.get('Content-Type')
    if (content_type == 'application/json'):
        json = request.json
        #return json['firstName']
    else:
        return 'Content-Type not supported!'
    '''
    # ----- SECTION 2 -----
    try:
        #status=json['lastname']
        decoded_img = request.files["image"]
        #decoded_img = base64.b64decode(json['firstName'])
        #img = Image.open(io.BytesIO(image.read()))
        img = Image.open(BytesIO(decoded_img.read()))
        #print("SANKARi")
        file_name = file_name_for_base64_data + ".jpg"
        #print(file_name)
        #img.save(file_name, "jpeg",quality=100)
        #np_data = np.frombuffer(decoded_img,np.uint8)
        #print("DE")
        #img21 = cv2.imdecode(np_data,cv2.IMREAD_UNCHANGED)
        img21 = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        
        #print(file_name+"sss")
        ###############NEW START
        image=img21
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        fm = variance_of_laplacian(gray)
        text = "Not Blurry"
        # if the focus measure is less than the supplied threshold,
        # then the image should be considered "blurry"
        if fm < 5.0:
            text = "Blurry"
            print(text)
            isGoodFeatures="FALSE"
            

        else:
            
            orb1 = cv2.ORB_create()
                # find the keypoints with ORB
            kp = orb1.detect(image,None)
            # compute the descriptors with ORB
            kp, des = orb.compute(image, kp)
            # draw only keypoints location,not size and orientation
            #img2 = cv.drawKeypoints(foreground, kp, None, color=(0,255,0), flags=0)
            if len(kp)>200:
                print(len(kp))
                img2=image
                isGoodFeatures="GOOD"
                #cv2.imwrite('foreground.jpg', img2)
            else:
                isGoodFeatures="FALSE"
            

        ###############NEW END
        

        

        if isGoodFeatures!="FALSE":
            desList = findDes(images)
            #print(len(desList))
            #img2 = cv2.imread("test/Suresh.jpg")  # Reading the image. Change the name according to your img name

            imgOriginal = img2.copy()
            img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
            img_blur = cv2.GaussianBlur(img2, (7, 7), 1)  # Making the image blurry
            img_edges = cv2.Canny(img_blur, 30, 30)  # Finding the edges in the image for detecting where the image is.
            img_dialation = cv2.dilate(img_edges, kernel,
                                       iterations=1)  # Dilating our image so that the edges detected by canny edge detector can be made thick.
            contours, hierarchy = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  # Detecting the contours(shapes)
            for cnt in contours:
                area = cv2.contourArea(cnt)  # checking the area of contours
                if area > 5000:  # there can be many countours so we are filtering it as our money area is large
                    peri = cv2.arcLength(cnt, True)  # Calculating our countour perimeter
                    approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)  # performimg an approximation of a shape of a contour.
                    x, y, w, h = cv2.boundingRect(approx)  # finding the x, y coordinates and height and width of our money
                    final_img = imgOriginal[y: y + h, x: x + w]  # Croping our image to get money only

                else:
                    final_img = img2  # returning our img2 image if the money is not detected and this situation comes when your image contains only money i.e. their is no any background.



            X = findID(final_img, desList)
            #print(matchlist)
            #print(len(matched1))
            #print(ClassNames)
            if X != -1:
                #status = "Image has been succesfully sent to the server."+ClassNames[X]
                addurlParent=ClassNames[X]
                print(addurlParent)
                #status=ClassNames[X]+jsonpickle.encode(matchlist)
                #print(status)
                connection = mysql.connector.connect(host='localhost',
                                                     database='arhimaya',
                                                     user='root',
                                                     password='Vision@3')
                sql_select_Query = "select * from others"
                # MySQLCursorDict creates a cursor that returns rows as dictionaries
                cursor = connection.cursor(dictionary=True)
                cursor.execute(sql_select_Query)
                records = cursor.fetchall()
                #print(addurlParent+"SA")
                #print("Fetching each row using column name")
                for row in records:
                    id = row["targetimagepath"]
                    #print(id)
                    #print(addurlParent)
                    #name = row["Name"]
                    #price = row["Price"]
                    if addurlParent == id:
                        
                        targetContent= row["targetcontent"]
                        status = targetContent
                        print(status+"Finished")
                        break
                    
                        #print(addurlParent+"DONE")
                    
                    #purchase_date = row["Purchase_date"]
                        

                    
               
                if connection.is_connected():
                    connection.close()
                    cursor.close()
                        #print("MySQL connection is closed")
                #cv2.putText(imgOriginal, ClassNames[X], (50, 50), cv2.FONT_HERSHEY_COMPLEX, 2, (0, 0, 255), 3)
                #print(status)
                
            else:
                status="WRONG"
        else:
            status="WRONG"
            

        # ----- SECTION 3 -----
        
    except Exception as e:
        status = "Error! = " + str(e)
    
    return status


if __name__ == '__main__':
    #app.run(host="192.168.1.4", port=5000)

    app.run()

