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

Copyright © 2022 Pixelgen Technologies AB.
"""

import dataclasses
from typing import List, Optional, TypedDict, TypeVar

from pixelator.mpx.report.models.commands import CommandInfo

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


@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-qc-report (0.4.0)
class Metrics(TypedDict, total=False):
    """A typed dictionary containing all metrics that can be used in the qc report.

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

    Note: This class is autogenerated from the metrics.json file (0.4.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

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

    #: Average reads per cell after performing the filtering stages of Pixelator to
    #: retrieve only confidently decoded MPX reads.
    average_reads_usable_per_cell: int

    #: Average reads per cell after Illumina Passed Filter step, removal of phiX as
    #: well as accounting for the actual number of 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

    #: The fraction of cells that are outliers as determined by the [tau-metric
    #: outlier
    #: detection](https://software.pixelgen.com/pixelator/algorithms#antibody-count-
    #: distribution-outliers).
    fraction_outlier_cells: float

    #: 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,cluster,cluster_cell_class,reads,molecules,mean_upia_degree,mean_umi_per_upia
    #: 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
    #: ```
    #: reads_per_molecule,count,frequency
    #: 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_molecule_frequency: Optional[str]
