from typing import List
from typing import Optional
from typing import Tuple

from marshmallow import fields

from ..daiquiri.mixin import DaiquiriProcessorMixin
from ..daiquiri.mixin import ExposedParameter
from ..daiquiri.validators import exists_list
from ..persistent.parameters import ParameterInfo
from ..resources import resource_filename
from ..utils import directories
from .processor import BlissScanType
from .processor import FluoProcessor


class DaiquiriFluoProcessor(
    FluoProcessor,
    DaiquiriProcessorMixin,
    parameters=[ParameterInfo("notification_queue", category="daiquiri")],
):
    DEFAULT_WORKFLOW: Optional[str] = resource_filename(
        "fluo", "daiquiri_xrfmap_single_detector.json"
    )

    EXPOSED_PARAMETERS = [
        ExposedParameter(
            parameter="workflow",
            field_type=fields.Str,
            title="Last workflow",
            read_only=True,
        ),
        ExposedParameter(
            parameter="pymca_configs",
            field_type=fields.List,
            title="PyMCA Config File(s)",
            field_options={"validate": exists_list},
            field_args=[fields.Str()],
        ),
        ExposedParameter(
            parameter="quantification",
            field_type=fields.Bool,
            title="Quantification",
        ),
    ]

    def scan_requires_processing(self, scan) -> bool:
        """Only execute this workflow if there is a `daiquiri_datacollectionid` in the `scan_info`"""
        if not super().scan_requires_processing(scan):
            return False
        if not scan.scan_info.get("daiquiri_datacollectionid"):
            return False
        return True

    def get_daiquiri_inputs(self, scan: BlissScanType, workflow: str):
        return [
            {
                "task_identifier": "StartJob",
                "name": "dataCollectionId",
                "value": scan.scan_info.get("daiquiri_datacollectionid"),
            },
            {
                "task_identifier": "StartJob",
                "name": "output_filename",
                "value": directories.master_output_filename(scan),
            },
            {
                "task_identifier": "StartJob",
                "name": "workflow",
                "value": workflow,
            },
            {
                "task_identifier": "StartJob",
                "name": "config",
                "value": {
                    "pymca_configs": ",".join(self.pymca_configs),
                },
            },
            {
                "task_identifier": "NotifyBeamline",
                "name": "beamline",
                "value": self.notification_queue,
            },
        ]

    def get_submit_arguments(
        self, scan: BlissScanType, inputs: List[dict]
    ) -> Tuple[str, dict]:
        """Merge in daiquiri StartJob options and use the ppf engine for error handling."""
        workflow, kwargs = super().get_submit_arguments(scan, inputs)
        kwargs["inputs"] += self.get_daiquiri_inputs(scan, workflow)
        kwargs["engine"] = "ppf"
        return workflow, kwargs

    def _get_workflow(self, scan: BlissScanType, workflow_stem: str) -> Optional[str]:
        """Use the daiquiri variant with Mimosa tasks."""
        return resource_filename("fluo", f"daiquiri_{workflow_stem}.json")
