
import logging
import os

from qmenta.sdk.tool_maker.outputs import (
    Coloring,
    HtmlInject,
    OrientationLayout,
    PapayaViewer,
    Region,
    ResultsConfiguration,
    Split,
    Tab,
)
from qmenta.sdk.tool_maker.modalities import Modality, Tag
from qmenta.sdk.tool_maker.tool_maker import InputFile, Tool, FilterFile


class TOOL_CLASS(Tool):
    def tool_inputs(self):
        """
        Define the inputs for the tool. This is used to create the settings.json file.
        More information on the inputs can be found here:
        https://docs.qmenta.com/sdk/guides_docs/settings.html
        """
        # Add the file selection method:
        self.add_input_container(
            title="Title of the setting",
            info="Describe here what is the expected input, this will appear in the tool UI.",
            anchor=1,
            batch=1,
            container_id="input_data",
            mandatory=1,
            file_list=[
                InputFile(
                    file_filter_condition_name="condition_t1_brain",
                    filter_file=FilterFile(
                        modality=Modality.T1,
                        tags=[Tag("brain")],
                        regex=".*",
                    ),
                    mandatory=1,
                    min_files=1,
                    max_files=1,
                ),
            ],
        )

        # The following calls will add different parameters to the settings JSON. Keep, edit or remove them
        # according to your specifications:

        # Display a text in the settings explaining the below parameters:
        self.add_indent("Parameters of the tool are accessed using the variable self.inputs.id_")

        # Display a checkbox parameter
        self.add_input_checkbox(id_="ex_checkbox", default=0, title="Checkbox setting type description")

        # Displays a short free text to input a string parameter
        self.add_input_string(id_="some_string", default="TOOL", title="String type description")

        # Displays a short free text to input a parameter of type integer
        self.add_input_integer(id_="some_integer", default=3, title="Integer type description", minimum=0, maximum=10)

        # Displays an horizontal line
        self.add_line()

        # Displays a short free text to input a parameter of type decimal
        self.add_input_decimal(
            id_="some_decimal", default=3.14, title="Decimal type description", minimum=0.1, maximum=4.3
        )

        # Displays a header text
        self.add_heading("Choice settings:")

        # Displays a text box in blue color with the information specified.
        self.add_info(
            "In the options, the first element in the list of tuples is the value representation that the "
            "tool handles, the second element is the string shown in the platform for humans to select."
        )

        # Adds a dropdown menu for the user to select a single option
        self.add_input_single_choice(
            id_="one_choice", options=[("a", "Option A"), ("b", "Option B"), ("c", "Option C")], default="b",
            title="Single choice type description"
        )

        # Displays a small menu where the user can select multiple options.
        self.add_input_multiple_choice(
            id_="multi_choice",
            options=[("a", "Option A"), ("b", "Option B"), ("c", "Option C")], default=["a", "b"],
            title="Multiple choice type description",
        )

    def run(self, context):
        """
        This is the main function that is called when the tool is run.
        """
        # ================ #
        # GETTING THINGS READY
        logger = logging.getLogger("main")
        logger.info("Tool starting")

        # Downloads all the files and populate the variable self.inputs with the handlers and parameters
        context.set_progress(message="Downloading input data and setting self.inputs object")
        self.prepare_inputs(context, logger)

        # Input handlers are built as simplenamespaces, each attribute is the "id" defined in each InputFile
        # THESE ARE LISTS, each element has the methods to get modality, tags, file_info
        schema_file = self.inputs.input_data.condition_t1_brain

        schema_file_path = schema_file[0].file_path  # getting the first element of the file handler list

        schema_file_modality = schema_file[0].get_file_modality()
        schema_file_tags = schema_file[0].get_file_tags()
        schema_file_file_info = schema_file[0].get_file_info()

        logger.info(
            f"Input file data."
            f"Path : {schema_file_path}"
            f"Modality: {schema_file_modality}"
            f"Tags: {schema_file_tags}"
            f"INFO: {schema_file_file_info}"
        )

        # Parameters are also accessible through the self.inputs object
        checkbox = self.inputs.ex_checkbox
        some_decimal = self.inputs.some_decimal
        logger.info(f"Parameter checkbox : {checkbox}")
        logger.info(f"Parameter decimal : {some_decimal}")

        # Working directory
        working_dir = os.environ.get("WORKDIR")  # from Dockerfile, feel free to modify
        out_folder = os.path.join(working_dir, "OUTPUT")
        os.makedirs(out_folder, exist_ok=True)

        # ================##
        # YOUR CODE HERE
        result_file = os.path.join(out_folder, "T1_final.nii.gz")
        with open(result_file, "w") as f1:
            f1.write("I have been processed.")
        # ================##

        # PREPARE AND UPLOAD YOUR RESULTS Example:
        context.set_progress(message="Uploading result")
        context.upload_file(
            source_file_path=result_file,  # path to the output file in Docker container
            destination_path="T1_final.nii.gz",  # path of the file saved in the output container in the platform
            modality=str(Modality.DTI),  # modality that will be set for that file
            tags={"eddy"}  # tags that will be set for that file
        )
        context.set_metadata_value(key="metadata_key", value=100)  # metadata value added to the session metadata
        # ================##

    def tool_outputs(self):
        result_conf = ResultsConfiguration()

        # Add the tools to visualize files using the function add_visualization
        papaya_1 = PapayaViewer(title="Tissue segmentation over T1", width="50%", region=Region.center)
        papaya_1.add_file(file="T1brain.nii.gz", coloring=Coloring.grayscale)  # using the file name
        papaya_1.add_file(file="tissueSegmentation.nii.gz", coloring=Coloring.custom)
        result_conf.add_visualization(new_element=papaya_1)

        # Add the required visualizations (papaya, html_inject, html_text)
        papaya_2 = PapayaViewer(title="Labels segmentation over T1", width="50%", region=Region.right)
        papaya_2.add_file(file="m'T1'", coloring=Coloring.grayscale)  # using the file modality
        papaya_2.add_file(file="t'seg'", coloring=Coloring.custom_random)  # using file tag
        result_conf.add_visualization(new_element=papaya_2)

        # To create a split, specify which ones are the objects to be shown in the split
        split_1 = Split(
            orientation=OrientationLayout.vertical, children=[papaya_1, papaya_2], button_label="Images"
        )

        html_online = HtmlInject(width="100%", region=Region.center, button_label="Report")
        html_online.add_html(file="online_report.html")
        result_conf.add_visualization(new_element=html_online)

        # Remember to add the button_label in the child objects of the tab.
        tab_1 = Tab(children=[split_1, html_online])
        # Call the function generate_results_configuration_file to create the final object that will be saved in the
        # tool path
        result_conf.generate_results_configuration_file(
            build_screen=tab_1, tool_path=self.tool_path, testing_configuration=False
        )

def run(context):
    TOOL_CLASS().tool_outputs()  # this can be removed if no results configuration file needs to be generated.
    TOOL_CLASS().run(context)