####coding: utf-8
'''
Created on 12 Mar 2018

@author: lbtanh
'''
from os.path import dirname, join, realpath
import sys
import argparse

from make_dataset import ROOT_DIR, seriallize_face_encodings
# from __future__ import division
import cv2
import glob, pickle, os
import numpy as np
from sklearn.svm import SVC, LinearSVC
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline, Pipeline

ENCODINGS_PER_INDIVIDUAL_THRESHOLD =  20
   
    
def test_classifier():    
    # ////////// load model //////////////////
    clf = pickle.load(open('SVM_linear.model', 'rb'))
    # ////// run predict on image //////////////
    img = resize_image('D:/Dataset/7_face/5380/5380_normal_1.jpg')
    image = np.array(img)
    face_encoding = face_recognition.face_encodings(image)
    if len(face_encoding) == 0:
        print("no face detected on this one")
    else:
        predict_image = np.array(face_encoding[0])
        result = clf.predict(predict_image.reshape(1, -1))

def create_classifier(X, y, clf_type):
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    print(X_train.shape)
    #Set the classifier as a support vector machines with polynomial kernel
    #     clf = SVC(kernel="poly", degree=3, coef0=1, C=5)
    #    ////////// training and save model//////////////// 
    shuffle_index = np.random.permutation(len(X_train))
    X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]
    print('Creating classifier: ' + clf_type)
    
    if clf_type == "l_svm":
#         clf = Pipeline((("scaler", StandardScaler()),("linear_svc", LinearSVC(C=1, loss="hinge")),))
        clf = SVC(kernel='linear', probability=True, tol=1e-3)#, verbose = True)
        model_path = 'SVM_linear.model'
        clf.fit(X_train, y_train)
        
    elif clf_type == 'nl_svm':
        model_path = 'non_linear.model'
        pipe_svc = make_pipeline(StandardScaler(),SVC(random_state=1))
        param_range = [0.0001, 0.001, 0.01, 0.1,1.0, 10.0, 100.0, 1000.0]
        param_grid = [{'svc__C': param_range,'svc__kernel': ['linear']},{'svc__C': param_range,'svc__gamma': param_range,'svc__kernel': ['rbf']}]
        clf = GridSearchCV(estimator=pipe_svc,param_grid=param_grid,scoring='accuracy',cv=5,n_jobs=-1)
        clf = clf.fit(X_train, y_train)
        print(clf.best_score_)

        print(clf.best_params_)   
        
    elif clf_type == "nn":
        clf = MLPClassifier(solver='lbfgs', alpha=1e-2,
                     hidden_layer_sizes=(512, 100), random_state=1)
        model_path = 'nn.model'
        clf.fit(X_train, y_train)
        print(clf)
        
    
    pickle.dump(clf, open(model_path, 'wb'))
    pred_score = clf.score(X_test, y_test)
    print("Prediction score: ", pred_score)


def parse_arguments(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('--is_train', required=False, default=1, 
        help='train model')
    parser.add_argument('--type_model', required=False, default='nl_svm', 
        help='')
    return parser.parse_args(argv)    

def main(args):
    if int(args.is_train):
        if args.type_model in ["nn", "l_svm", "nl_svm"]:
            # X, y = [pickle.load(open(data+'.pickle', 'rb')) for data in ['X', 'y']]
            face_embeddings_path = join(ROOT_DIR, 'models/embeddings/face_encodings_2.pickle')
            X, Y = seriallize_face_encodings(face_embeddings_path, 10)
            print(len(X), len(Y))
            create_classifier(X, Y, args.type_model)
        else:
            print("Unexpected type of classifier")

        
if __name__=='__main__':
    main(parse_arguments(sys.argv[1:]))

    