# Logging utils from:
# https://github.com/cszn/DPIR/blob/master/utils/utils_logger.py#L26
# https://github.com/xinntao/BasicSR

import sys
import datetime
import logging
from PIL import Image

import numpy as np
from scipy import signal

import jax.numpy as jnp


def gkern(kernlen=21, std=3):
    """Returns a 2D Gaussian kernel array."""
    gkern1d = signal.gaussian(kernlen, std=std).reshape(kernlen, 1)
    gkern2d = np.outer(gkern1d, gkern1d)
    kernel = jnp.array(np.sqrt(gkern2d[..., np.newaxis, np.newaxis]))
    kernel = jnp.repeat(kernel, 3, axis=3)
    return kernel/(kernel).sum()*3


def tensor_to_img(x):
    out = jnp.squeeze(x)
    if len(out.shape) == 3:  # If color image, we transpose back to HWC
        out = jnp.transpose(out, [1, 2, 0])
    return out


def save_image(im_array, im_name):
    im_array = np.array(im_array)
    im_array = np.clip(im_array, 0, 1)
    result = Image.fromarray((im_array * 255).astype(np.uint8))
    result.save(im_name)


def save_dict_to_file(dic, path):
    f = open(path, 'w+')
    f.write(str(dic))
    f.close()


def compute_metrics(x_target, x_input, x_output):
    metrics = {}
    for task in range(x_target.shape[0]):
        mse_input = jnp.mean(jnp.square(x_target[task] - x_input[task]))
        mse = jnp.mean(jnp.square(x_target[task] - x_output[task]))
        metrics_task = {
            'mse': mse,
            'psnr input': 10 * jnp.log10(1 / mse_input),
            'snr input': 10 * jnp.log10(jnp.mean(jnp.square(x_target[task])) / mse_input),
            'psnr': 10 * jnp.log10(1 / mse),
            'snr': 10 * jnp.log10(jnp.mean(jnp.square(x_target[task])) / mse),
        }
        metrics.update({'task '+str(task): metrics_task})
    return metrics


def log(*args, **kwargs):
    print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S:"), *args, **kwargs)


def logger_info(logger_name, log_path='default_logger.log'):
    log = logging.getLogger(logger_name)
    # For some reason, below doesn't work
    # if log.hasHandlers():
    #     print('LogHandlers exists!')
    # else:
    #     print('LogHandlers setup!')
    level = logging.INFO
    formatter = logging.Formatter('%(asctime)s.%(msecs)03d : %(message)s', datefmt='%y-%m-%d %H:%M:%S')
    fh = logging.FileHandler(log_path, mode='a')
    fh.setFormatter(formatter)
    log.setLevel(level)
    log.addHandler(fh)

    sh = logging.StreamHandler()
    sh.setFormatter(formatter)
    log.addHandler(sh)


class logger_print(object):
    def __init__(self, log_path="default.log"):
        self.terminal = sys.stdout
        self.log = open(log_path, 'a')

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)  # write the message

    def flush(self):
        pass