import cv2
import dlib
import numpy as np
#from numeric import *

import math
import openface
import openface.helper
from openface.data import iterImgs

import sys
import os
import glob
import argparse
from PIL import Image as pilimage

from keras.models import load_model
from keras.preprocessing import image

import random
import time

# Propia
import utils
import gender as gd
import clothes
#import skinDetect as skin


def load_image(image_path, grayscale=False, target_size=None):
    pil_image = image.load_img(image_path, grayscale, target_size)
    return image.img_to_array(pil_image)

# Obtenir vector caracteristic de la cara.
def getRep(imgPath, align, net , aviso=False, imgDim=96):
    
    #parser.add_argument('--dlibFacePredictor', type=str, help="Path to dlib's face predictor.",
    #                default=os.path.join(dlibModelDir, "shape_predictor_68_face_landmarks.dat"))
    #parser.add_argument('--networkModel', type=str, help="Path to Torch network model.",
    #                default=os.path.join(openfaceModelDir, 'nn4.small2.v1.t7'))
    
    #align = openface.AlignDlib(args.dlibFacePredictor)
    #net = openface.TorchNeuralNet(args.networkModel, args.imgDim)
    #imgDim = 96  # que el argumeto original era args.imgDim
    
    #align = openface.AlignDlib(os.path.join(dlibModelDir, "shape_predictor_68_face_landmarks.dat"))
    #net = openface.TorchNeuralNet(os.path.join(openfaceModelDir, 'nn4.small2.v1.t7'), imgDim)
    
    
    if aviso:
        print("Processing {}.".format(imgPath))
    
    bgrImg = cv2.imread(imgPath)
    
    if bgrImg is None:
        #raise Exception("Unable to load image: {}".format(imgPath))
        #return ['Error'] # En caso de errores
        return None #'Error'
    
    rgbImg = cv2.cvtColor(bgrImg, cv2.COLOR_BGR2RGB)

    if aviso:
        print("  + Original size: {}".format(rgbImg.shape))
    
    start = time.time()
    bb = align.getLargestFaceBoundingBox(rgbImg)
    if bb is None:
        #raise Exception("Unable to find a face: {}".format(imgPath))
        #return ['Error'] # En caso de error
        return None #'Error'
        
    if aviso:
        print("  + Face detection took {} seconds.".format(time.time() - start))

    start = time.time()
    alignedFace = align.align(imgDim, rgbImg, bb,
                            landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE)
    if alignedFace is None:
        #raise Exception("Unable to align image: {}".format(imgPath))
        #return ['Error'] #En caso de error
        return None #'Error'
        
    if aviso:
        print("  + Face alignment took {} seconds.".format(time.time() - start))

    start = time.time()
    rep = net.forward(alignedFace)
    
    if aviso:
        print("  + OpenFace forward pass took {} seconds.".format(time.time() - start))
        #print("Representation:")
        #print(rep)
        print("-----\n")


    return rep #Vector caracteristico de la imagen


# Funcio per guardar els vectors d una persona concreta i poder utilitzar per localitzars
#tipo -> ['face','face-clothes']
def saveRepsFace(inputDir, bdDir, nameFace, align, net, imgDim=96, aviso = False, tipo = 'face'):
    
    #Comprovar si existe el origen de las fotos
    if os.path.exists(inputDir):
        
        # Iniciar variables
        errors = []
        m, per = 0, -1 
        
        # Imagenes de medio cuerpo
        images = glob.glob(inputDir+'/*.png') #Se usara tambien como labels
        n = len(images)
        reps =[-1]*n # formatar el vector resultant
        repsClothes = [-1]*n #Valoracio roba
        repsGender = [-1]*n #Valoracio sexe
        
        if aviso:
            print ''
            print " Obtenint Vectors de caracteristiques de " + str(n) + " Imatges de " + nameFace
            print "---------------------------------------------------------"
        
        
        for img in images:
            #Es crea un objecte amb totes les referencies per aixi analitzar
            image = utils.ImageFace(img)
            
            #Posar el vector de la cara
            image.setVecFace(getRep(img, align, net, False, imgDim))
            
            # Sols calcular les imatges que es puguin vectoritzar
            if image.getVecFace() is not None:
                
                #Posar el vector de la roba
                if image.getCoords() is not None:
                    image.setVecClothes(clothes.getClothes(img,image.getCoords()))
                    image.generateVecFaceClothes()
                else:
                    image.setVecClothes('ErrorRopaCoordenades')
            
            
            #Guardar tots els vectors a reps per retornar-los una vegada comprovats els errors
            reps[m] = image #getRep(img, align, net, False, imgDim)
            
            # Per gestionar la barra de progres per si la visualitzacio esta activa a True
            if aviso:
                if per < int((m/float(n))*100):
                    per = int((m/float(n))*100)
                    utils.progressBar(per)
            m += 1

        
        # Cercar errors al tenir numero de referencia 
        i = 0
        for rep in reps:
            if rep.getVecFace() is None:
                errors.append(i) # es crea llista ordenada dels index amb errors
            i += 1
        
        # vuidar images amb errors
        i = 0
        for rm in errors:
            #print 'Indice a eliminar ' + str(rm-i)
            reps.pop(rm-i)
            repsClothes.pop(rm-i)
            errors[i] = images.pop(rm-i)
            i += 1

        
        # Visualizar el final del proceso        
        if aviso:
            utils.progressBar(100)
            sys.stdout.write("\x1B[37m") # Canvia de color a normal
            print('\n')
        
        # Guardar els vectors en un csv 
        if not os.path.exists(bdDir):
            os.mkdir(bdDir)
        for rep in reps:
            if tipo == 'face':
                utils.writeCsv(bdDir+'/'+nameFace+'.csv',rep.getVecFace())
            if tipo == 'face-clothes':
                utils.writeCsv(bdDir+'/'+nameFace+'.csv',rep.getVecFaceClothes())
        print "Vectors guardats a " + bdDir+'/'+nameFace+'.csv'
        print "Errors produits: " + str(len(errors))
        
    else:
        print "Directorio Origen inexistente"
    


# Comprar imatges entre elles
def compareImages(img1,img2):
    d = getRep(img1) - getRep(img2)
    #print("Comparing {} with {}.".format(img1, img2))
    #print("  + Squared l2 distance between representations: {:0.3f}".format(np.dot(d, d)))
    
    return np.dot(d, d)

# compara la distancia entre dos vectors
def compareVectors(vec1,vec2):
    
    d = vec1 - vec2
    return np.dot(d,d)

# Dona el resultat de comparativa per mitjana entre dos vectors
def compareVectorsAverage(vec1,vec2):
    
    return (sum(promVecs([vec1,vec2])))/(len(vec1)*len(vec2))

# realitzar promig dels vectors entrats per llista
def promVecs(vecs):
    n = len(vecs)
    if n > 0:
        new_vec = []
        nPos = len(vecs[0])
        
        for i in range(0,nPos):
            suma = 0.0
            for vec in vecs:
                suma += vec[i]
                
            new_vec.append(suma/float(n))
    
        return new_vec
    else:
        return None # no hi ha vectors


# Convertir el vector en 1 i -1 per fer un primer filtratge
def vecsOnes(vectors,one = 1, other = 0):    
    vecs = [[one if float(x) > 0.0 else other for x in rep] for rep in vectors]

    return vecs

# Gestion para obtener los distintos vectores de las imagenes sin torch
def extractVectors(inputDir, align, net, gender_classifier, args, imgDim=96, aviso = False):
    
    #Comprovar si existe el origen de las fotos
    if os.path.exists(inputDir):
        
        #gender_labels = get_labels('imdb')
        #gender_labels = {0:'Dona', 1:'Home'}
        font = cv2.FONT_HERSHEY_SIMPLEX

        # hyper-parameters for bounding boxes shape
        gender_offsets = (30, 60)
        gender_offsets = (10, 10)


        # loading models
        #face_detection = load_detection_model(detection_model_path)
        #gender_classifier = load_model(gender_model_path, compile=False)
        
        # Iniciar variables
        errors = []
        m, per = 0, -1 
        
        # Imagenes de medio cuerpo
        images = glob.glob(inputDir+'/*.png') #Se usara tambien como labels
        n = len(images)
        reps =[None]*n # formatar el vector resultant
        #repsClothes = [-1]*n
        #repsGender = [-1]*n #determinar sexe
        
        if aviso:
            print ''
            print " Obtenint Vectors de caracteristiques de " + str(n) + " cara(es)"
            print "---------------------------------------------------------"
        
        
        for img in images:
            #Es crea un objecte amb totes les referencies per aixi analitzar
            image = utils.ImageFace(img)
            
            #Posar el vector de la cara
            image.setVecFace(getRep(img, align, net, False, imgDim))
            
            # Sols calcular les imatges que es puguin vectoritzar
            if image.getVecFace() is not None:
                
                #Posar el vector de la roba
                if image.getCoords() is not None:
                    image.setVecClothes(clothes.getClothes(img,image.getCoords(),skin = args.skin))
                    image.generateVecFaceClothes()
                else:
                    image.setVecClothes('ErrorRopaCoordenades')
                
                # Per gestionar la barra de progres per si la visualitzacio esta activa a True
                if aviso:
                    if per < int((m/float(n))*100):
                        per = int((m/float(n))*100)
                        utils.progressBar(per)
            
            #Guardar el objecte en el vector
            reps[m] = image
            m += 1

        
        # Cercar errors al tenir numero de referencia i buscar sexe
        for i in range(0,len(reps)):
            if reps[i].getVecFace() is None:
                errors.append(i) # es crea llista ordenada dels index amb errors
            else:
                # loading images
                rgb_image = load_image(reps[i].getPath(), grayscale=False)
                gray_image = load_image(reps[i].getPath(), grayscale=True)
                gray_image = np.squeeze(gray_image)
                gray_image = gray_image.astype('uint8')
                
                #Classificador de genere
                faceCoords = image.getCoords()
                if faceCoords is not None:
                    x1, x2, y1, y2 = gd.apply_offsets(faceCoords, gender_offsets)
                    rgb_face = rgb_image[y1:y2, x1:x2]
                    
                    #Posar el sexe de la persona
                    sexe = gd.getGender(rgb_face, gender_classifier)
                    reps[i].setSex(sexe)
                else:
                    sexe = -1
                    reps[i].setSex(-1)
                
                if sexe is None:
                    print reps[i].getPath()
                    errors.append(i) #Al no poder determinar correctament sexe es descarta
        
        # vuidar images amb errors
        i = 0
        for rm in errors:
            errors[i] = reps.pop(rm-i).getPath()
            i += 1

        
        # Visualizar el final del proceso        
        if aviso:
            utils.progressBar(100)
            sys.stdout.write("\x1B[37m") # Canvia de color a normal
            print('\n')
        
        #guardar els vectors en un fitxer
        #i=0
        #test = []
        #for img in images:
        #   test.append(img+';'+str(list(reps[i])))
        #   i +=1
        #for er in errors:
        #    test.append(er+';Error')
           
        #utils.ioFitxer('vectores.txt','a', test)
        
        #return [images,reps,errors,repsClothes] #Devuelve las etiquetes con sus valores de representacion
        return [reps,errors]
            
    else:
        print "Directorio Origen inexistente"
