"""Read .hc files."""

# Author: Eric Larson <larson.eric.d<gmail.com>
#
# License: BSD-3-Clause

import numpy as np

from ...utils import logger
from .res4 import _make_ctf_name
from .constants import CTF
from ..constants import FIFF


_kind_dict = {'nasion': CTF.CTFV_COIL_NAS, 'left ear': CTF.CTFV_COIL_LPA,
              'right ear': CTF.CTFV_COIL_RPA, 'spare': CTF.CTFV_COIL_SPARE}

_coord_dict = {'relative to dewar': FIFF.FIFFV_MNE_COORD_CTF_DEVICE,
               'relative to head': FIFF.FIFFV_MNE_COORD_CTF_HEAD}


def _read_one_coil_point(fid):
    """Read coil coordinate information from the hc file."""
    # Descriptor
    one = '#'
    while len(one) > 0 and one[0] == '#':
        one = fid.readline()
    if len(one) == 0:
        return None
    one = one.strip().decode('utf-8')
    if 'Unable' in one:
        raise RuntimeError("HPI information not available")

    # Hopefully this is an unambiguous interpretation
    p = dict()
    p['valid'] = ('measured' in one)
    for key, val in _coord_dict.items():
        if key in one:
            p['coord_frame'] = val
            break
    else:
        p['coord_frame'] = -1

    for key, val in _kind_dict.items():
        if key in one:
            p['kind'] = val
            break
    else:
        p['kind'] = -1

    # Three coordinates
    p['r'] = np.empty(3)
    for ii, coord in enumerate('xyz'):
        sp = fid.readline().decode('utf-8').strip()
        if len(sp) == 0:  # blank line
            continue
        sp = sp.split(' ')
        if len(sp) != 3 or sp[0] != coord or sp[1] != '=':
            raise RuntimeError('Bad line: %s' % one)
        # We do not deal with centimeters
        p['r'][ii] = float(sp[2]) / 100.0
    return p


def _read_hc(directory):
    """Read the hc file to get the HPI info and to prepare for coord trans."""
    fname, found = _make_ctf_name(directory, 'hc', raise_error=False)
    if not found:
        logger.info('    hc data not present')
        return None
    s = list()
    with open(fname, 'rb') as fid:
        while True:
            p = _read_one_coil_point(fid)
            if p is None:
                # First point bad indicates that the file is empty
                if len(s) == 0:
                    logger.info('hc file empty, no data present')
                    return None
                # Returns None if at EOF
                logger.info('    hc data read.')
                return s
            if p['valid']:
                s.append(p)
