"""
Implement file operations such as read/write files here.
@author: <NAME> (y(dot)meng201011(at)gmail(dot)com)
"""

import csv
from collections import namedtuple

from utils.config import *
from utils.plot import plot_comparisons

class ORIENT(object):
    COL = 'col'
    ROW = 'row'

def dict2csv(dictionary, file_name, list_as_value=False):
    """
    Serialize values in given dictionary to a csv file.
    :param dictionary: the dictionary to save.
    :param file_name: the name of the csv file, including the path.
    :param list_as_value: each key has a list of values.
    """
    print(dictionary)
    with open(file_name, 'w') as outfile:
        writer = csv.writer(outfile, delimiter=',')
        if list_as_value:
            """
            The dictionary is in form of
            {
            key : [values]
            }
            """
            writer.writerow(dictionary.keys())
            writer.writerows(zip(*dictionary.values()))
        else:
            """
            The dictionary is in form of
            {
            key : value
            }
            """
            for row in dictionary.items():
                writer.writerow(row)

def csv2dict(file_name, orient=ORIENT.COL, dtype='float'):
    """
    Load csv into a dictionary in the form of
    {
        key : [values]
    }
    :param file_name: csv file name includes the full path
    :param orient:
        orient.col: values of the keys are in a column
        orient.row: values of the keys are in a row
    :param dtype: data type of values
    :return: the dictionary
    """
    if ORIENT.COL == orient:
        with open(file_name) as file:
            reader = csv.reader(file)
            col_headers = next(reader, None)

            columns = {}
            for header in col_headers:
                columns[header] = []

            for row in reader:
                for header, value in zip(col_headers, row):
                    if 'float' == dtype:
                        value = float(value)
                    columns[header].append(value)

        return columns

    else: # ORIENT.ROW == orient
        # TODO: implement
        rows = {}
        return rows


def save_adv_examples(data, **kwargs):
    """
    Serialize generated adversarial examples to an npy file.
    :param data: the adversarial examples to store.
    :param kwargs: information needed to construct the file name
    :return: na
    """
    prefix = kwargs.get('prefix', 'test')
    dataset = kwargs.get('dataset', 'cifar10')
    architect = kwargs.get('architect', 'cnn')
    transformation = kwargs.get('transformation', 'clean')
    attack_method = kwargs.get('attack_method', 'fgsm')
    attack_params = kwargs.get('attack_params', None)
    bs_samples = kwargs.get('bs_samples', None)

    prefix = '{}_AE'.format(prefix)
    attack_info = '{}_{}'.format(attack_method, attack_params)
    model_info = '{}-{}-{}'.format(dataset, architect, transformation)
    file_name = '{}-{}-{}.npy'.format(prefix, model_info, attack_info)
    np.save('{}/{}'.format(PATH.ADVERSARIAL_FILE, file_name), data)

    if MODE.DEBUG:
        if bs_samples is not None:
            title = '{}-{}'.format(model_info, attack_info)
            plot_comparisons(bs_samples[:10], data[:10], title)
        else:
            print('Print AEs only')
            title = '{}-{}'.format(model_info, attack_info)
            plot_comparisons(data[:10], data[10:20], title)

    print('Adversarial examples saved to {}/{}.'.format(PATH.ADVERSARIAL_FILE, file_name))
"""
Implement file operations such as read/write files here.
@author: <NAME> (y(dot)meng201011(at)gmail(dot)com)
"""

import csv
from collections import namedtuple

from utils.config import *
from utils.plot import plot_comparisons

class ORIENT(object):
    COL = 'col'
    ROW = 'row'

def dict2csv(dictionary, file_name, list_as_value=False):
    """
    Serialize values in given dictionary to a csv file.
    :param dictionary: the dictionary to save.
    :param file_name: the name of the csv file, including the path.
    :param list_as_value: each key has a list of values.
    """
    print(dictionary)
    with open(file_name, 'w') as outfile:
        writer = csv.writer(outfile, delimiter=',')
        if list_as_value:
            """
            The dictionary is in form of
            {
            key : [values]
            }
            """
            writer.writerow(dictionary.keys())
            writer.writerows(zip(*dictionary.values()))
        else:
            """
            The dictionary is in form of
            {
            key : value
            }
            """
            for row in dictionary.items():
                writer.writerow(row)

def csv2dict(file_name, orient=ORIENT.COL, dtype='float'):
    """
    Load csv into a dictionary in the form of
    {
        key : [values]
    }
    :param file_name: csv file name includes the full path
    :param orient:
        orient.col: values of the keys are in a column
        orient.row: values of the keys are in a row
    :param dtype: data type of values
    :return: the dictionary
    """
    if ORIENT.COL == orient:
        with open(file_name) as file:
            reader = csv.reader(file)
            col_headers = next(reader, None)

            columns = {}
            for header in col_headers:
                columns[header] = []

            for row in reader:
                for header, value in zip(col_headers, row):
                    if 'float' == dtype:
                        value = float(value)
                    columns[header].append(value)

        return columns

    else: # ORIENT.ROW == orient
        # TODO: implement
        rows = {}
        return rows


def save_adv_examples(data, **kwargs):
    """
    Serialize generated adversarial examples to an npy file.
    :param data: the adversarial examples to store.
    :param kwargs: information needed to construct the file name
    :return: na
    """
    prefix = kwargs.get('prefix', 'test')
    dataset = kwargs.get('dataset', 'cifar10')
    architect = kwargs.get('architect', 'cnn')
    transformation = kwargs.get('transformation', 'clean')
    attack_method = kwargs.get('attack_method', 'fgsm')
    attack_params = kwargs.get('attack_params', None)
    bs_samples = kwargs.get('bs_samples', None)

    prefix = '{}_AE'.format(prefix)
    attack_info = '{}_{}'.format(attack_method, attack_params)
    model_info = '{}-{}-{}'.format(dataset, architect, transformation)
    file_name = '{}-{}-{}.npy'.format(prefix, model_info, attack_info)
    np.save('{}/{}'.format(PATH.ADVERSARIAL_FILE, file_name), data)

    if MODE.DEBUG:
        if bs_samples is not None:
            title = '{}-{}'.format(model_info, attack_info)
            plot_comparisons(bs_samples[:10], data[:10], title)
        else:
            print('Print AEs only')
            title = '{}-{}'.format(model_info, attack_info)
            plot_comparisons(data[:10], data[10:20], title)

    print('Adversarial examples saved to {}/{}.'.format(PATH.ADVERSARIAL_FILE, file_name))
Implement file operations such as read/write files here. @author: <NAME> (y(dot)meng201011(at)gmail(dot)com) Serialize values in given dictionary to a csv file.     :param dictionary: the dictionary to save.     :param file_name: the name of the csv file, including the path.     :param list_as_value: each key has a list of values. The dictionary is in form of             {             key : [values]             } The dictionary is in form of             {             key : value             } Load csv into a dictionary in the form of     {         key : [values]     }     :param file_name: csv file name includes the full path     :param orient:         orient.col: values of the keys are in a column         orient.row: values of the keys are in a row     :param dtype: data type of values     :return: the dictionary # ORIENT.ROW == orient # TODO: implement Serialize generated adversarial examples to an npy file.     :param data: the adversarial examples to store.     :param kwargs: information needed to construct the file name     :return: na