import warnings


def data_order(iaf, ibf, order, multite=False):
    """
    Determine the data format and ordering from ``iaf`` and ``ibf`` options

    If ``iaf`` is not specified (None or empty string), TC pairs are specified if the
    ``order`` parameter is given and contains the ``l`` character. Otherwise differenced
    data is assumed.

    If neither ``ibf`` nor ``order`` are specified, ``ibf=rpt`` is guessed.

    If ``iaf`` is not ``diff`` and ``order`` does not include the ``l` character it is assumed
    that the encoded images (e.g. TC pairs) are the fastest varying.

    If any parameters had to be guessed (rather than inferred from other information) a
    warning is output.

    :return: Tuple of: IAF (ASL format, 'tc', 'ct', 'diff', 've', 'vediff', 'hadamard' or 'mp'), ordering (sequence of
             2 or three chars, 'l'=labelling images, 'r'=repeats, 't'=TIs/PLDs, 'e'=TEs. The characters
             are in order from fastest to slowest varying), Boolean indicating whether the block
             format needed to be guessed
    """
    if order is not None:
        order = order.lower()

    if not iaf:
        if order is not None and "l" in order:
            # Order specified labelling images so guess TC pairs as this is most common
            warnings.warn("Data format was not specified - assuming TC pairs")
            iaf = "tc"
        elif not order:
            # No order specified  - guess differenced for compatibility with Oxford ASL
            warnings.warn("Data format was not specified - assuming differenced")
            iaf = "diff"
        else:
            # Order specified and did not include labelling images so we are entitled
            # to assume differenced data without a warning
            iaf = "diff"
    elif iaf not in ("diff", "tc", "ct", "mp", "ve", "vediff", "hadamard"):
        raise ValueError("Unrecognized data format: iaf=%s" % iaf)

    ibf_guessed = False
    if not order:
        if not ibf:
            # Guess but defer warning until we have extracted TIs as it doesn't matter
            # for single TI data
            ibf = "rpt"
            ibf_guessed = True

        order_map = {
            "rpt" : "tr",
            "tis" : "rt",
        }
        order = order_map.get(ibf.lower(), None)
        if not order:
            raise ValueError("Unrecognized data block format: ibf=%s" % ibf)

    if iaf != "diff" and "l" not in order:
        order = "l" + order

    if multite and "e" not in order:
        # TE ordering is optional since most data is single TE. Insert it at the
        # start as this seems to make most sense in terms of multi-TE acquisition
        order = "e" + order

    for char in order:
        if char not in ('l', 'r', 't', 'e'):
            raise ValueError("Unrecognized character in data ordering: '%s'" % char)

    return iaf, order, ibf_guessed