# -*- coding: utf-8 -*-

import logging
from os import path
import numpy as np
from skimage import exposure

import vrl


logger = vrl.utils.get_logger('sartb')
vrl.utils.set_loglevel(logging.INFO)


def get_config(file):
    if(not path.exists(file)):
        logging.error('Error: config file {} does not exist.'.format(file))

    assert(path.exists(file))
    config = open(file).readlines()
    assert(len(config) > 4)
    nrow = int(config[1])
    ncol = int(config[4])
    return nrow, ncol


def get_channel(file, nrow, ncol):
    if(not path.exists(file)):
        logging.error('Error: file {} does not exist.'.format(file))

    assert(path.exists(file))
    channel = np.fromfile(file, dtype=np.float32).reshape((nrow, ncol))

    return channel


def read_polsar(ipath, mode='real'):
    assert(mode in ['real', 'imag', 'mod', 'com'])
    ipath = ipath + '/{}'
    config = ipath.format('config.txt')
    nrow, ncol = get_config(config)
    ncha = 9  # 3x3 matrix

    #polsar[0, 0, :] = [p11, p12, p13,
    #                   p21, p22, p23,
    #                   p31, p32, p33]

    polsar = np.zeros((nrow, ncol, ncha), dtype=np.complex64)
    format = [('T11.bin', 0), ('T22.bin', 4), ('T33.bin', 8)]
    #read diagonal (real numbers)
    for file, pos in format:
        polsar[:, :, pos] = get_channel(ipath.format(file), nrow, ncol)

    #read non diagonal (complex numbers)
    format = [('T12_real.bin', 'T12_imag.bin', 1), ('T13_real.bin', 'T13_imag.bin', 2),
              ('T23_real.bin', 'T23_imag.bin', 5)]
    for real, imag, pos in format:
        real = get_channel(ipath.format(real), nrow, ncol)
        imag = get_channel(ipath.format(imag), nrow, ncol)
        polsar[:, :, pos] = real + 1j * imag

    if(mode is 'real'):
        polsar = np.real(polsar)
    elif(mode is 'imag'):
        polsar = np.imag(polsar)
    elif(mode is 'mod'):
        polsar = np.abs(polsar)

    # Hermitic values
    polsar[:, :, 3] = np.conjugate(polsar[:, :, 1])
    polsar[:, :, 6] = np.conjugate(polsar[:, :, 2])
    polsar[:, :, 7] = np.conjugate(polsar[:, :, 5])

    return polsar


def force_positive_definite(polsar):
    nrow, ncol, ncha = polsar.shape
    dim = int(np.sqrt(ncha))
    for y in range(nrow):
        for x in range(ncol):
            X = polsar[y, x].reshape(dim, dim)
            if(not is_positive_definite_hermitian(X)):
                X = vrl.ml.utils.force_positive_definite(X)
                polsar[y, x] = X.ravel()


def is_positive_definite_hermitian(x):
    if(x.ndim == 1):
        dim = int(np.sqrt(x.shape[0]))
        x.reshape(dim, dim)

    eigvals = np.linalg.eigvalsh(x)
    return np.all(eigvals > 0.0)


def gen_rgb_from_polsar(polsar):
    assert(polsar.ndim == 3)
    nrow, ncol, nch = polsar.shape
    rgb = np.zeros((nrow, ncol, 3))
    rgb[:, :, 0] = np.copy(polsar[:, :, 0])
    rgb[:, :, 1] = np.copy(polsar[:, :, 4])
    rgb[:, :, 2] = np.copy(polsar[:, :, 8])
    rgb = exposure.adjust_gamma(rgb, .1)
    return rgb
