#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import sys
import os.path as op

from pprint import pformat
from optparse import OptionParser

import nibabel
import numpy as np

import pyhrf
from pyhrf.tools._io.tio import Texture
from pyhrf.tools._io.spmio import load_paradigm_from_mat, load_contrasts_from_mat

from pyhrf.parcellation import parcellation_report


def describe_mat_file(filename):
    paradigm, tr = load_paradigm_from_mat(filename)
    print '*** Paradigm data ***'
    for sess in sorted(paradigm.keys()):
        datasession = paradigm[sess]
        print 'session:', sess
        for cond in sorted(datasession['onsets'].keys()):
            print '  ', cond, ':'
            print '    ', 'ons:', datasession['onsets'][cond]
            print '    ', 'dur:', datasession['stimulusLength'][cond]
    print '*** Functional data ***'
    print 'TR =', tr
    print '*** Constrasts ***'

    conts = load_contrasts_from_mat(filename)
    for i, c in enumerate(conts):
        print '%d (%s): %s ' % (i + 1, str(c), str(conts[c]))


def describeArray(a):

    if (a.astype(int) == a).all():
        a = a.astype(int)
        print '-> integer values'
        print 'values, mean(std)[min...max]:\n %1.4f(%1.4f)[%d...%d]' \
            % (a.mean(), a.std(), a.min(), a.max())
        u = np.unique(a)
        print 'unique values:'
        print u
        print 'counts:'
        bc = np.bincount(a)
        bc = bc[bc != 0]
        print 'values, mean(std)[min...max]:\n %1.4f(%1.4f)[%d...%d]' \
            % (bc.mean(), bc.std(), bc.min(), bc.max())
        print np.vstack((u, bc)).transpose()


def describe_nii_file(filename):
    s = ''
    i = nibabel.load(filename)
    h = i.get_header()
    s += '*Nifti file*' + '\n'
    s += 'Description: ' + str(h['descrip']) + '\n'
    s += 'Voxel dimensions: ' + ','.join(map(str, h['pixdim'])) + '\n'
    s += 'Data shape: ' + str(i.get_shape()) + '\n'
    s += 'Qform:' + '\n'
    s += str(h.get_qform()) + '\n'
    if not (h.get_sform() == 0).all():
        s += 'Sform:' + '\n'
        s += str(h.get_sform()) + '\n'
    else:
        s += 'SForm is null' + '\n'
    d = i.get_data()
    nb_nans = np.isnan(d).sum()
    if nb_nans > 0:
        s += '* Found %d NaNs\n' % nb_nans

    if ('parcellation' in h['descrip'] or np.allclose(np.round(d), d)) and \
            len(np.unique(d)) < 5000 and d.ndim < 4:
        s += parcellation_report(d)

    else:
        s += '* Values, mean(std)[min...max]: %1.4f(%1.4f)[%1.2f...%1.2f]\n' \
            % (d[~np.isnan(d)].mean(), d[~np.isnan(d)].std(),
               d[~np.isnan(d)].min(), d[~np.isnan(d)].max()) + '\n'
    return s


def describeTexFile(filename):
    print 'Texture file:'
    d = Texture.read(filename)
    d.show()
    describeArray(d.data)

usage = 'usage: %%prog [options] FILE'

description = 'Print info from a data FILE'

parser = OptionParser(usage=usage, description=description)

parser.add_option('-v', '--verbose', dest='verbose', metavar='VERBOSELEVEL',
                  type='int', default=0,
                  help=pformat(pyhrf.verbose_levels))

(options, args) = parser.parse_args()
# pyhrf.verbose.set_verbosity(options.verbose)
pyhrf.logger.setLevel(options.verbose)

# Treat result of option parsing:
if len(args) != 1:
    parser.print_help()
    sys.exit(1)


filename = args[0]
bnf, ext = op.splitext(filename)

if ext == '.tex':
    describeTexFile(filename)
elif ext == '.nii' or (ext == '.gz' and filename.split('.')[-2] == 'nii') \
        or ext == '.img':
    print describe_nii_file(filename)
elif ext == '.mat':
    describe_mat_file(filename)
else:
    print 'unrecognised extension:', ext
