#!/usr/bin/env python

import os.path as op
import re

import simplejson

from boutiques.logger import print_info, raise_error
from boutiques.validator import DescriptorValidationError


# BIDS validation module
def validate_bids(descriptor, valid=False):

    if not valid:
        msg = "Please provide a Boutiques descriptor that has been validated."
        raise_error(DescriptorValidationError, msg)

    errors = []

    # TODO: verify not only that all fields/keys exist, their properties, too

    # Ensure the command-line conforms to the BIDS app spec
    msg_template = "   CLIError: command-line doesn't match template: {}"
    cltemp = (
        r"mkdir -p \[OUTPUT_DIR\]; (.*) \[BIDS_DIR\] \[OUTPUT_DIR\]"
        r" \[ANALYSIS_LEVEL\] \[PARTICIPANT_LABEL\] \[SESSION_LABEL\]"
        r"[\\s]*(.*)"
    )
    cmdline = descriptor["command-line"]
    if len(re.findall(cltemp, cmdline)) < 1:
        errors += [msg_template.format(cltemp)]

    # Verify IDs are present which link to the OUTPUT_DIR
    # key bot as File and String
    ftypes = {"File", "String"}
    msg_template = '   OutError: "{}" types for outdir do not match "{}"'
    outtypes = {
        inp["type"]
        for inp in descriptor["inputs"]
        if inp["value-key"] == "[OUTPUT_DIR]"
    }
    if outtypes != ftypes:
        errors += [msg_template.format(", ".join(outtypes), ", ".join(ftypes))]

    # Verify that analysis levels is an enumerable with some
    # subset of "participant", "session", and "group"
    choices = ["session", "participant", "group"]
    msg_template = ' LevelError: "{}" is not a valid analysis level'
    alevels = [
        inp["value-choices"]
        for inp in descriptor["inputs"]
        if inp["value-key"] == "[ANALYSIS_LEVEL]"
    ][0]
    errors += [msg_template.format(lv) for lv in alevels if lv not in choices]

    # Verify there is only a single output defined (the directory)
    msg_template = "OutputError: 0 or multiple outputs defined"
    if len(descriptor["output-files"]) != 1:
        errors += [msg_template]
    else:
        # Verify that the output shows up as an output
        msg_template = "OutputError: OUTPUT_DIR is not represented as an output"
        if descriptor["output-files"][0]["path-template"] != "[OUTPUT_DIR]":
            errors += [msg_template]

    errors = None if errors == [] else errors
    if errors is None:
        print_info("BIDS validation OK")
    else:
        raise_error(
            DescriptorValidationError,
            "Invalid BIDS app descriptor:" "\n" + "\n".join(errors),
        )
