
from timeit import default_timer as timer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score,confusion_matrix,roc_curve,auc
import config as cf
from  sklearn.feature_selection import  chi2 , f_classif , mutual_info_classif , SelectKBest
import numpy as np


# def feature_methods(df,labels):
#   '''
#   This function will apply feature selection on the input set
#   :param df: The raw dataFrame passed to be feature selected.
#   :param labels: labers of the raw dataset.
#   '''
#   chi_2 = SelectKBest(chi2, k = 10000).fit_transform( df , labels )
#   f_measure = SelectKBest(f_classif, k = 10000).fit_transform( df , labels )
#   mutual_info = SelectKBest(mutual_info_classif, k = 10000).fit_transform( df , labels )
#   return [chi_2,f_measure,mutual_info]

def feature_methods(df,labels ):
    '''
    This function will apply feature selection on the input set
    :param df: The raw dataFrame passed to be feature selected.
    :param labels: labers of the raw dataset.
    '''
    import numpy as np
    chi_2 = SelectKBest(chi2, k = df.shape[1]).fit( df , labels )
    f_measure = SelectKBest(f_classif, k = df.shape[1]).fit( df , labels )
    mutual_info = SelectKBest(mutual_info_classif, k = df.shape[1]).fit( df , labels )
    #return [chi_2. ,f_measure. get_feature_names_out(input_features=columns),mutual_info. get_feature_names_out(input_features=columns)]
    #return [chi_2. get_feature_names_out(input_features=columns),f_measure. get_feature_names_out(input_features=columns),mutual_info. get_feature_names_out(input_features=columns)]
    return [df.iloc[:,(chi_2.pvalues_).argsort()].to_numpy(),df.iloc[:,(f_measure.pvalues_).argsort()].to_numpy(),df.iloc[:,(-mutual_info.scores_).argsort()].to_numpy()]
    #return [np.argsort(chi_2.pvalues_),np.argsort(f_measure.pvalues_),(-mutual_info.scores_).argsort()]
  

def different_size( size  , classifier , index , index_fs, each_fs,labels):
  '''
  This function will be able compute accuracy based on the classifier, feature_Size and feature_method 
  :param size: the feature size to be used.
  :param classifier: the classifier to be used. 
  :param index: index for a item in global_list list
  :param index_fs: index for a item in global_fs list
  :param each_fs: The feature selection method to employ
  '''
  local_dict = {}
  #X_train, X_test, y_train, y_test =  train_test_split(each_fs[:,:size] , labels , random_state = 0 );
  X_train, X_test, y_train, y_test =  train_test_split(each_fs[:,:int(each_fs.shape[1] * size)] , labels , random_state = 0 );
  start = timer()
  clf =  classifier.fit( X_train , y_train );
  end = timer()
  preds =  clf.predict(X_test) ;
  local_dict['clf'] = cf.global_list[index]
  local_dict['fs'] = cf.global_fs[index_fs]
  local_dict['size'] = size
  local_dict['model_time'] =  float(format(end - start , '.2f')) 
  local_dict['accuracy'] = float(format((accuracy_score( preds , y_test)  * 100),'.2f'))
  return local_dict


def compute_accuracy( clf  , name ,X_train, y_train,X_test,y_test):
  result = {}
  result['clf'] = name
  start = timer()
  model =  clf.fit( X_train , y_train );
  end = timer()
  preds =  model.predict(X_test);
  result['Time'] =  float(format(end - start , '.2f')) 
  result['accuracy'] =  float(format((accuracy_score( preds , y_test)  * 100),'.2f')) 
  return result

def compute_roc_auc( clf,name ,df, labels):
  X_train,X_test, y_train,y_test = train_test_split( df , labels , random_state = 0 )
  result = {}
  result['clf'] = name
  start = timer()
  model =  clf.fit( X_train , y_train );
  end = timer()
  preds =  model.predict(X_test);
  result['Time'] =  float(format(end - start , '.2f')) 
  result['accuracy'] =  float(format((accuracy_score( preds , y_test)  * 100),'.2f'))
  result['Conf'] = confusion_matrix(y_test,preds)
  result['fprRD'], result['tprRD'], threshold = roc_curve(y_test, preds)
  result['roc_aucRD'] = auc(result['fprRD'], result['tprRD']) 
  return result