# -*- coding: utf-8 -*-
# Authors: Denis A. Engemann <denis.engemann@gmail.com>
#          Eric Larson <larson.eric.d@gmail.com>
# License: Simplified BSD

from os import path as op

import numpy as np
from scipy.sparse import csc_matrix

from .open import read_tag, fiff_open
from .tree import dir_tree_find
from .write import (start_block, end_block, write_int, write_float,
                    write_string, write_float_matrix, write_int_matrix,
                    write_float_sparse_rcs, write_id)
from .tag import find_tag
from .constants import FIFF
from ..externals.six import text_type, string_types
from ..utils import warn


_proc_keys = ['parent_file_id', 'block_id', 'parent_block_id',
              'date', 'experimenter', 'creator']
_proc_ids = [FIFF.FIFF_PARENT_FILE_ID,
             FIFF.FIFF_BLOCK_ID,
             FIFF.FIFF_PARENT_BLOCK_ID,
             FIFF.FIFF_MEAS_DATE,
             FIFF.FIFF_EXPERIMENTER,
             FIFF.FIFF_CREATOR]
_proc_writers = [write_id, write_id, write_id,
                 write_int, write_string, write_string]
_proc_casters = [dict, dict, dict,
                 np.array, text_type, text_type]


def _read_proc_history(fid, tree, info):
    """Read processing history from fiff file

    This function reads the SSS info, the CTC correction and the
    calibaraions from the SSS processing logs inside af a raw file
    (C.f. Maxfilter v2.2 manual (October 2010), page 21):

    104 = {                 900 = proc. history
      104 = {               901 = proc. record
        103 = block ID
        204 = date
        212 = scientist
        113 = creator program
        104 = {             502 = SSS info
          264 = SSS task
          263 = SSS coord frame
          265 = SSS origin
          266 = SSS ins.order
          267 = SSS outs.order
          268 = SSS nr chnls
          269 = SSS components
          278 = SSS nfree
          243 = HPI g limit    0.98
          244 = HPI dist limit 0.005
        105 = }             502 = SSS info
        104 = {             504 = MaxST info
          264 = SSS task
          272 = SSST subspace correlation
          279 = SSST buffer length
        105 = }
        104 = {             501 = CTC correction
          103 = block ID
          204 = date
          113 = creator program
          800 = CTC matrix
          3417 = proj item chs
        105 = }             501 = CTC correction
        104 = {             503 = SSS finecalib.
          270 = SSS cal chnls
          271 = SSS cal coeff
        105 = }             503 = SSS finecalib.
      105 = }               901 = proc. record
    105 = }                 900 = proc. history
    """
    proc_history = dir_tree_find(tree, FIFF.FIFFB_PROCESSING_HISTORY)
    out = list()
    if len(proc_history) > 0:
        proc_history = proc_history[0]
        proc_records = dir_tree_find(proc_history,
                                     FIFF.FIFFB_PROCESSING_RECORD)
        for proc_record in proc_records:
            record = dict()
            for i_ent in range(proc_record['nent']):
                kind = proc_record['directory'][i_ent].kind
                pos = proc_record['directory'][i_ent].pos
                for key, id_, cast in zip(_proc_keys, _proc_ids,
                                          _proc_casters):
                    if kind == id_:
                        tag = read_tag(fid, pos)
                        record[key] = cast(tag.data)
                        break
                else:
                    warn('Unknown processing history item %s' % kind)
            record['max_info'] = _read_maxfilter_record(fid, proc_record)
            smartshields = dir_tree_find(proc_record,
                                         FIFF.FIFFB_SMARTSHIELD)
            if len(smartshields) > 0:
                # XXX should eventually populate this
                ss = [dict() for _ in range(len(smartshields))]
                record['smartshield'] = ss
            if len(record['max_info']) > 0:
                out.append(record)
        if len(proc_records) > 0:
            info['proc_history'] = out


def _write_proc_history(fid, info):
    """Write processing history to file"""
    if 'proc_history' not in info:
        return
    if len(info['proc_history']) > 0: