"""Helper classes to define the data input for the qc report.

Copyright (c) 2022 Pixelgen Technologies AB.
"""
import dataclasses
import typing
from typing import List, Optional, TypeVar, TypedDict


CommandOptionValue = TypeVar("CommandOptionValue", str, int, float, bool)


@dataclasses.dataclass
class CommandOption(typing.Generic[CommandOptionValue]):
    """Dataclass for passing command options/flags to qc report."""

    #: The name of the option (e.g. `--min-reads`)
    name: str
    #: The value of the option.
    value: CommandOptionValue
    #: The default value for this option.
    default_value: Optional[CommandOptionValue]
    #: The help text for this option.
    description: Optional[str]


@dataclasses.dataclass
class CommandInfo:
    """Dataclass for passing all options of a command to qc report."""

    #: The name of the parameter group.
    command: str
    #: A list of options for the parameter group.
    options: List[CommandOption]


@dataclasses.dataclass
class SampleInfo:
    """Dataclass for general sample information.

    The values defined here are used in the dynamic qc report to populate the
    "sample information" panel.
    """

    #: Version of pixelator used to generate the metrics
    pixelator_version: str

    #: Date the report was generated
    generation_date: str

    #: Identifier of the sample
    sample_id: str

    #: Short description of the sample
    sample_description: str

    #: Version of the pixel
    pixel_version: str

    #: Name of the pixelator panel file
    panel_name: Optional[str]

    #: Version of the pixelator panel file
    panel_version: Optional[str]

    #: List of commands and their parameters
    parameters: List[CommandInfo]


# --- START AUTOGENERATED: metrics ---
# using metrics.json from pixelator-webreport (0.3.0)
class Metrics(TypedDict, total=False):
    """A typed dictionary containing all metrics that can be used in the webreport.

    Values defined here will be used in the dynamic webreport to populate
    the different data tables. Missing values will be left blank.

    Note: This class is autogenerated from the metrics.json file (0.3.0)
    """

    #: Number of library reads that contain an Antibody DNA-barcode from a Pixelgen
    #: Technologies panel.
    antibody_reads: int

    #: Number of Antibody library reads that contain a recognized Antibody DNA-
    #: barcode, a valid UMI, valid PBS adapters and valid UPI Molecular Pixelation
    #: identifiers.
    antibody_reads_usable_per_cell: int

    #: Number of Antibody library reads that were filtered after annotation and tau-
    #: metric outlier detection.
    antibody_reads_in_outliers: int

    #: Number of Antibody library reads that contain an unrecognizable antibody
    #: barcode.
    unrecognized_antibodies: int

    #: Fraction of library reads that contain an Antibody DNA-barcode from a Pixelgen
    #: Technologies panel.
    fraction_antibody_reads: float

    #: Fraction of Antibody library reads that contain a recognized Antibody DNA-
    #: barcode, a valid UMI, valid PBS adapters and valid UPI Molecular Pixelation
    #: identifiers.
    fraction_antibody_reads_usable_per_cell: float

    #: Fraction of Antibody library reads that were filtered after annotation and
    #: tau-metric outlier detection.
    fraction_antibody_reads_in_outliers: float

    #: Fraction of Antibody library reads that contain an unrecognizable antibody
    #: barcode.
    fraction_unrecognized_antibodies: float

    #: Fraction of Antibody library reads in Cells with a recognized Antibody DNA-
    #: barcode, a valid UMI, valid PBS adapters and valid UPI Molecular Pixelation
    #: identifiers.
    fraction_antibody_reads_in_cells: float

    #: Number of predicted B-cells.
    predicted_cell_type_b_cells: int

    #: Fraction of predicted B-cells.
    fraction_predicted_cell_type_b_cells: float

    #: Number of predicted CD4+ cells.
    predicted_cell_type_cd4p_cells: int

    #: Fraction of predicted CD4+ cells.
    fraction_predicted_cell_type_cd4p_cells: float

    #: Number of predicted CD8+-cells.
    predicted_cell_type_cd8p_cells: int

    #: Fraction of predicted CD8+-cells.
    fraction_predicted_cell_type_cd8p_cells: float

    #: Number of predicted Monocytes.
    predicted_cell_type_monocytes: int

    #: Fraction of predicted Monocytes.
    fraction_predicted_cell_type_monocytes: float

    #: Number of predicted NK-cells
    predicted_cell_type_nk_cells: int

    #: Fraction of predicted NK-cells
    fraction_predicted_cell_type_nk_cells: float

    #: Number of predicted cells with unknown cell type.
    predicted_cell_type_unknown: int

    #: Fraction of predicted cells with unknown cell type.
    fraction_predicted_cell_type_unknown: float

    #: Number of cells in clusters predicted to contain multiple different cell
    #: types.
    predicted_cell_type_multiclass: int

    #: Fraction of cells in clusters predicted to contain multiple different cell
    #: types.
    fraction_predicted_cell_type_multiclass: float

    #: Number of cells in clusters predicted to be dead.
    predicted_cell_type_dead: int

    #: Fraction of cells in clusters predicted to be dead.
    fraction_predicted_cell_type_dead: float

    #: The number of cells annotated by the pipeline.
    number_of_cells: int

    #: The average of confidently-decoded Molecular Pixelation reads associated to
    #: cells.
    average_reads_usable_per_cell: int

    #: The average of raw Molecular Pixelation reads associated to cells.
    average_reads_per_cell: int

    #: The average number of molecules associated to antibodies on annotated cells.
    average_antibody_molecules_per_cell: float

    #: The average number of UMIs per A-pixel.
    average_umis_per_upia: int

    #: The average number of A-pixels per cell identified.
    average_upias_per_cell: int

    #: The percentage of sequenced reads usable in cells. A usable read contains a
    #: recognized Antibody DNA-barcode, a valid UMI, valid PBS adapters and valid UPI
    #: Molecular Pixelation identifiers.
    fraction_reads_in_cells: float

    #: The percentage of UMIs in non-cell components.
    fraction_discarded_umis: float

    #: The total number of antibodies with at least {min-count} reads from molecules
    #: (UMI+UPI) in any cell.
    total_unique_antibodies_detected: int

    #: Total number of read pairs that were input to this library.
    number_of_reads: int

    #: Total number of read pairs ignored by the pipeline that do not satisfy the
    #: minimum length requirements.
    number_of_short_reads_skipped: int

    #: Fraction of reads found with valid Molecular Pixelation binding adapter.
    fraction_valid_pbs: float

    #: Fraction of reads with valid molecules that passed filters and were used to
    #: build graph components.
    fraction_valid_umis: float

    #: The proportion of reads from already found molecules (UMI+UPI). This metric
    #: will be a function of library complexity and sequencing depth. More
    #: specifically, this is the fraction of duplicated reads from the same Molecular
    #: Pixelation amplicon.
    sequencing_saturation: float

    #: The average number of reads per molecule is a measure of sequencing depth in
    #: the sample and hints if the underlying molecule distribution has been well
    #: characterized.
    average_reads_per_molecule: float

    #: Fraction of Antibody Barcode bases with Q-score ≥ 30, excluding very low
    #: quality/no-call (Q ≤ 2) bases from the denominator.
    fraction_q30_bases_in_antibody_barcode: float

    #: Fraction of UMI bases with Q-score ≥ 30, excluding very low quality/no-call (Q
    #: ≤ 2) bases from the denominator.
    fraction_q30_bases_in_umi: float

    #: Fraction of UPIA bases with Q-score ≥ 30, excluding very low quality/no-call
    #: (Q ≤ 2) bases from the denominator.
    fraction_q30_bases_in_upia: float

    #: Fraction of UPIB bases with Q-score ≥ 30, excluding very low quality/no-call
    #: (Q ≤ 2) bases from the denominator.
    fraction_q30_bases_in_upib: float

    #: Fraction of PBS1 bases with Q-score ≥ 30, excluding very low quality/no-call
    #: (Q ≤ 2) bases from the denominator.
    fraction_q30_bases_in_pbs1: float

    #: Fraction of PBS2 bases with Q-score ≥ 30, excluding very low quality/no-call
    #: (Q ≤ 2) bases from the denominator.
    fraction_q30_bases_in_pbs2: float

    #: Fraction of R1 and R2 bases with Q-score ≥ 30, excluding very low quality/no-
    #: call (Q ≤ 2) bases from the denominator.
    fraction_q30_bases_in_read: float


# --- END AUTOGENERATED: metrics ---


class InfoAndMetrics(TypedDict):
    """Aggregated info and metrics."""

    info: SampleInfo
    metrics: Metrics


@dataclasses.dataclass
class QCReportData:
    """Collection of data inputs for dynamic figures in the qc report.

    All attributes are strings containing csv or json data ready to be
    injected into the dynamic report.
    """

    #: CSV formatted string containing a DataFrame  for the
    #: "component_size_distribution" figure
    #: component_size, rank, selected, markers
    #: 18463, 1, True, 32
    #: 18290, 2, True, 39
    ranked_component_size: Optional[str]

    #: CSV formatted string containing a DataFrame used for plotting embeddings
    #: with various colors,
    #: eg (cell type, leiden cluster, umis)
    #: Following columns are required:
    #:  component,umap1,umap2,umis,cluster,cluster_cell_class
    #: For example:
    #: ```
    #: component,umap1,umap2,umis,cluster,cluster_cell_class
    #: 0,11.891996,12.216717,4793,2,other
    #: 1,11.02211,12.486254,6708,2,other
    #: 2,7.8869944,7.5836325,5031,5,predict_B-cells
    #: 3,0.66538113,4.00765,3446,9,predict_CD4+_T-cells
    #: 4,13.21712,5.2930307,6704,1,predict_B-cells
    #: ```
    component_data: Optional[str]

    #: CSV formatted string containing a DataFrame used to generate the antibodies
    #: per cell figure
    #: Following columns are required: antibodies,reads
    #: For example:
    #: ```
    #: reads,antibodies
    #: 0,0
    #: 5000,5
    #: 5450,10
    #: 10900,15
    #: ```
    antibodies_per_cell: Optional[str]

    #: CSV formatted string containing a DataFrame used to generate the sequencing
    #: saturation figure.
    #: Following columns are required: reads,saturation
    #: For example:
    #: ```
    #: reads,saturation
    #: 0,0
    #: 5000,0.1609
    #: 5450,0.1736057
    #: ```
    sequencing_saturation: Optional[str]

    #: CSV formatted string containing a DataFrame used to generate the antibodies
    #: per cell figure.
    #: Following columns are required: antibody,percentage
    #: For example:
    #: ```
    #: antibody,percentage
    #: CD274,0.0016104640666519112
    #: CD44,0.04755881148351282
    #: CD56,0.020829214318265954
    #: ```
    antibody_percentages: Optional[str]

    #: CSV formatted string containing a DataFrame used to generate the antibody
    #: counts violin plots.
    #: It consists of the component column followed by a list of antibody columns.
    #: For example:
    #: ```
    #: component,CD274,CD44,CD56
    #: PXLCMP0000000,9.0,76.0,63.0
    #: PXLCMP0000002,3.0,90.0,166.0
    #: PXLCMP0000003,1.0,44.0,113.0
    #: ```
    antibody_counts: Optional[str]

    #: CSV formatted string containing a DataFrame used to generate the reads per UMI
    #: histogram.
    #: It consists of a frequency table with absolute and relative counts for the
    #: "count" field of the edgelist
    #: ```
    #: 2, 667338, 0.143356
    #: 3, 675999, 0.145216
    #: 4, 645161, 0.138592
    #: 5, 580468, 0.124695
    #: 6, 491899, 0.105668
    #: 7, 397472, 0.085384
    #: 8, 311331, 0.066879
    #: 9, 236724, 0.050852
    #: 10, 176052, 0.037819
    #: 11, 130251, 0.02798
    #: ```
    reads_per_umi_frequency: Optional[str]
