# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

import os.path as op
from io import BytesIO

import numpy as np

from ...annotations import Annotations
from .info import _convert_time
from .res4 import _read_res4


def _get_markers(fname):
    def consume(fid, predicate):  # just a consumer to move around conveniently
        while predicate(fid.readline()):
            pass

    def parse_marker(string):  # XXX: there should be a nicer way to do that
        data = np.genfromtxt(
            BytesIO(string.encode()), dtype=[("trial", int), ("sync", float)]
        )
        return int(data["trial"]), float(data["sync"])

    markers = dict()
    with open(fname) as fid:
        consume(fid, lambda line: not line.startswith("NUMBER OF MARKERS:"))
        num_of_markers = int(fid.readline())

        for _ in range(num_of_markers):
            consume(fid, lambda line: not line.startswith("NAME:"))
            label = fid.readline().strip("\n")

            consume(fid, lambda line: not line.startswith("NUMBER OF SAMPLES:"))
            n_markers = int(fid.readline())

            consume(fid, lambda line: not line.startswith("LIST OF SAMPLES:"))
            next(fid)  # skip the samples header
            markers[label] = [parse_marker(next(fid)) for _ in range(n_markers)]

    return markers


def _get_res4_info_needed_by_markers(directory):
    """Get required information from CTF res4 information file."""
    # we only need a few values from res4. Maybe we can read them directly
    # instead of parsing the entire res4 file.
    res4 = _read_res4(directory)

    total_offset_duration = res4["pre_trig_pts"] / res4["sfreq"]
    trial_duration = res4["nsamp"] / res4["sfreq"]

    meas_date = (_convert_time(res4["data_date"], res4["data_time"]), 0)
    return total_offset_duration, trial_duration, meas_date


def _read_annotations_ctf(directory):
    total_offset, trial_duration, meas_date = _get_res4_info_needed_by_markers(
        directory
    )
    return _read_annotations_ctf_call(
        directory, total_offset, trial_duration, meas_date
    )


def _read_annotations_ctf_call(directory, total_offset, trial_duration, meas_date):
    fname = op.join(directory, "MarkerFile.mrk")
    if not op.exists(fname):
        return Annotations(list(), list(), list(), orig_time=meas_date)
    else:
        markers = _get_markers(fname)

        onset = [
            synctime + (trialnum * trial_duration) + total_offset
            for _, m in markers.items()
            for (trialnum, synctime) in m
        ]

        description = np.concatenate(
            [np.repeat(label, len(m)) for label, m in markers.items()]
        )

        return Annotations(
            onset=onset,
            duration=np.zeros_like(onset),
            description=description,
            orig_time=meas_date,
        )
