"""Miscellaneous utility functions."""
import errno
import os
import numpy as np


def inmap(f, x, args=None):
    """
    Apply f to every el of x, in place.

    Applies a function (f) to every element of a list (x), in place.
    Adapted from http://stackoverflow.com/questions/3000461/python-map-in-place
    """
    for i, v in enumerate(x):
        if args is None:
            f(v)
        else:
            f(v, *args)


def mkdir_p(path):
    """
    Create directory as necessary.

    If path doesn't exist, creates directories necessary
    for it to exist. Avoids race condition, b/c only
    one system call.
    Source:
        http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
    """
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise


def fprint(arr):
    """
    Fully print out array
    """
    old = np.get_printoptions()['threshold']
    np.set_printoptions(threshold=np.inf)
    print arr
    np.set_printoptions(threshold=old)


def merge_dicts(*dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.

    Source: https://stackoverflow.com/a/26853961
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result


def _float_feature(value):
    import tensorflow as tf
    return tf.train.Feature(float_list=tf.train.FloatList(value=value))


def _int64_feature(value):
    import tensorflow as tf
    return tf.train.Feature(int64_list=tf.train.Int64List(value=value))


def _bytes_feature(value):
    import tensorflow as tf
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))
