import os
import fileinput
import sys
from Utils import readConfigurations, removeFiles, makeDir, checkifFileExists
import subprocess
import re
import importlib
from os import path

# first we need to do grid search for the given model
# after grid search get the parameters for the best model and edit the config file
# run for each feature based on the input to this script.
# for each run generate table and put it on notebook

# #first run the gridsearch 
# gridSearchFile = $1
# $(python3 $1 > gridsearch.txt)

# #now grep for best and select the param with least
# fName = 'gridsearch.txt'
# result = `grep -i 'Best:' $fname`

#load this into the config file, which is also a parameter
# configFile = $2
def replaceAll(file,searchExp,replaceExp):
    for line in fileinput.input(file, inplace=1):
        if searchExp in line:
            exp = re.search(searchExp+".*", line).group(0)
            line = line.replace(exp,replaceExp)
        sys.stdout.write(line)

def changeConfigFile(configs, configFile):
    cmd = "grep -i 'Best:' "+ configs['current_benchmark']+"_gridsearch.txt"
    p = subprocess.Popen(cmd,stdout = subprocess.PIPE,shell=True)
    (output, err) = p.communicate()
    p_status = p.wait()
    output = output.decode("utf-8")
    params = re.findall("\{(.*?)\}",output)[0]
    strbetBrackets = re.findall("\[(.*?)\]",output)
    mseTest = strbetBrackets[0]
    layer_size = strbetBrackets[1]
    hidden_size = strbetBrackets[2]
    print("The Best MSE for params %s and layer %s and hidden size %s is %s"%(params,layer_size,hidden_size,mseTest))
    model_string = "model_parameters = { "+ params + ", 'layer_size': "+layer_size + ", 'hidden_size': "+ hidden_size +" }"
    replaceAll(configFile,"model_parameters =",model_string)

    foldData_dir = "fold_data_dir = ./Models/"+configs['current_benchmark']+"/"+layer_size+"_"+hidden_size+"/"
    
    replaceAll(configFile,"fold_data_dir =",foldData_dir)

def gridSearch(configs, fold,configFile):
    print("Carrying out Grid Search for benchmark "+configs['current_benchmark'])
    n_folds = configs['n_folds']
    gridSearchCmd = "python3 "+ configs['grid_search_model'] + " " +str(fold)+ " " +str(n_folds)+" > "+ configs['current_benchmark']+"_gridsearch.txt"
    print("The command to run is %s"%(gridSearchCmd))
    p = subprocess.Popen(gridSearchCmd,stderr = subprocess.PIPE,shell=True)
    (output, err) = p.communicate()
    p_status = p.wait()
    print("Finished gridsearching")
    changeConfigFile(configs, configFile)

    

def run(configFile):
    #read the file and run for each index
    print("Reading from configurations at "+configFile)
    configs = readConfigurations(configFile)
    # configs = readConfigurations(configFile)
    sys.path.append('./src/Models')
    generateModel = importlib.__import__(configs['model']).generateModel

    for fold in range(0,configs['n_folds']):
        file = configs['current_benchmark']+"_gridsearch.txt"
        if path.exists(file) == False:
            print("file doesnt exist")
            gridSearch(configs,fold,configFile)
        else:
            changeConfigFile(configs, configFile)
        #generate initial models for all folds
        bestinitialmodel_dir = configs['fold_data_dir']+str(fold)+"/initial/"
        if not checkifFileExists(bestinitialmodel_dir,'model.h5'):
        # removeFiles(bestinitialmodel_dir)
            epoch = configs['model_parameters']['epochs']
            b_size = configs['model_parameters']['batch_size']
            lr = configs['model_parameters']['lr']
            layer_size = configs['model_parameters']['layer_size']
            hidden_size = configs['model_parameters']['hidden_size']
            generateModel(configs['data_path'],configs['fold_data_dir'],configs['n_folds'],fold, int(layer_size), hidden_size,epoch, b_size, lr,True,bestinitialmodel_dir)
    #get an initial model that is same for all features
    indexCount = 0

    if int(configs['solve_separate']) == 0:
        print("Generating results for "+ str(configs['indices']))
        replaceAll(configFile, "monotonic_indices =","monotonic_indices = "+str(','.join(map(str,configs['indices']))))
        cmd = "python3 src/Verification_framework.py " + configFile
        print("The command to run is %s"%(cmd))
        p = subprocess.Popen(cmd,stderr = subprocess.PIPE,shell=True)
        (output, err) = p.communicate()
        p_status = p.wait()
        print("Finished verifying")
    else:
        for index in configs['indices']:
            print("Generating results for "+configs['counter_generator'])
            replaceAll(configFile, "monotonic_indices =","monotonic_indices = "+str(index))
            replaceAll(configFile, "monotonicity_directions =","monotonicity_directions = "+str(configs['mon_dir'][indexCount]))
            cmd = "python3 src/Verification_framework.py " + configFile
            print("The command to run is %s"%(cmd))
            p = subprocess.Popen(cmd,stderr = subprocess.PIPE,shell=True)
            (output, err) = p.communicate()
            p_status = p.wait()
            print("Finished verifying")
            indexCount = indexCount + 1

args = sys.argv
run(args[1])