# Path: utils/load_externals.py

# 
# Path: utils/output.py
# def disablePrint(log_fpath=None):
#     sys.stdout.flush()
#     if log_fpath is None:
#         log_fpath = os.devnull
#     sys.stdout = open(log_fpath, 'w')
# 
# def enablePrint():
#     sys.stdout.flush()
#     log_f = sys.stdout
#     sys.stdout = sys.__stdout__
#     log_f.close()


import sys, os
import click
import pdb
import numpy as np
from utils import load_externals
from utils.output import disablePrint, enablePrint
from keras.models import Model
from keras.layers import Lambda, Input
from nn_robust_attacks.l2_attack import CarliniL2
from nn_robust_attacks.li_attack import CarliniLi
from nn_robust_attacks.l0_attack import CarliniL0

def generate_carlini_l0_examples(sess, model, x, y, X, Y, attack_params, verbose, attack_log_fpath):
    model_wrapper = wrap_to_carlini_model(model, X, Y)

    if 'batch_size' in attack_params:
        batch_size = attack_params['batch_size']
        del attack_params['batch_size']
    else:
        batch_size= 10

    accepted_params = ['targeted', 'learning_rate', 'max_iterations', 'abort_early', 'initial_const', 'largest_const', 'reduce_const', 'decrease_factor', 'const_factor', 'independent_channels', 'confidence']
    for k in attack_params:
        if k not in accepted_params:
            raise NotImplementedError("Unsuporrted params in Carlini L0: %s" % k)

    attack = CarliniL0(sess, model_wrapper, **attack_params)

    X_adv_list = []

    with click.progressbar(range(0, len(X)), file=sys.stderr, show_pos=True, 
                           width=40, bar_template='  [%(bar)s] Carlini L0 Attacking %(info)s', 
                           fill_char='>', empty_char='-') as bar:
        for i in bar:
            if i % batch_size == 0:
                X_sub = X[i:min(i+batch_size, len(X)),:]
                Y_sub = Y[i:min(i+batch_size, len(X)),:]
                if not verbose:
                    disablePrint(attack_log_fpath)
                X_adv_sub = attack.attack(X_sub - 0.5, Y_sub) + 0.5
                if not verbose:

# Path: utils/load_externals.py

# 
# Path: utils/output.py
# def disablePrint(log_fpath=None):
#     sys.stdout.flush()
#     if log_fpath is None:
#         log_fpath = os.devnull
#     sys.stdout = open(log_fpath, 'w')
# 
# def enablePrint():
#     sys.stdout.flush()
#     log_f = sys.stdout
#     sys.stdout = sys.__stdout__
#     log_f.close()


# Path: attacks/carlini_wrapper.py
import sys, os
import click
import pdb
import numpy as np
from utils import load_externals
from utils.output import disablePrint, enablePrint
from keras.models import Model
from keras.layers import Lambda, Input
from nn_robust_attacks.l2_attack import CarliniL2
from nn_robust_attacks.li_attack import CarliniLi
from nn_robust_attacks.l0_attack import CarliniL0


def generate_carlini_l0_examples(sess, model, x, y, X, Y, attack_params, verbose, attack_log_fpath):
    model_wrapper = wrap_to_carlini_model(model, X, Y)

    if 'batch_size' in attack_params:
        batch_size = attack_params['batch_size']
        del attack_params['batch_size']
    else:
        batch_size= 10

    accepted_params = ['targeted', 'learning_rate', 'max_iterations', 'abort_early', 'initial_const', 'largest_const', 'reduce_const', 'decrease_factor', 'const_factor', 'independent_channels', 'confidence']
    for k in attack_params:
        if k not in accepted_params:
            raise NotImplementedError("Unsuporrted params in Carlini L0: %s" % k)

    attack = CarliniL0(sess, model_wrapper, **attack_params)

    X_adv_list = []

    with click.progressbar(range(0, len(X)), file=sys.stderr, show_pos=True, 
                           width=40, bar_template='  [%(bar)s] Carlini L0 Attacking %(info)s', 
                           fill_char='>', empty_char='-') as bar:
        for i in bar:
            if i % batch_size == 0:
                X_sub = X[i:min(i+batch_size, len(X)),:]
                Y_sub = Y[i:min(i+batch_size, len(X)),:]
                if not verbose:
                    disablePrint(attack_log_fpath)
                X_adv_sub = attack.attack(X_sub - 0.5, Y_sub) + 0.5
                if not verbose:

                    enablePrint()