from __future__ import annotations
from collections.abc import Callable
from typing import Any
from ..fable_library.list import (of_array, FSharpList)
from ..fable_library.reflection import (TypeInfo, class_type)
from ..fable_library.seq import (map, iterate_indexed)
from ..fable_library.types import Array
from .data_context import (DataContext, DataContext__get_Explication, DataContext__set_Explication_279AAFF2, DataContext__get_Unit, DataContext__set_Unit_279AAFF2, DataContext__get_ObjectType, DataContext__set_ObjectType_279AAFF2, DataContext__get_Description, DataContext__set_Description_6DFDD678, DataContext__Copy)
from .Helper.hash_codes import (hash_1, box_hash_seq)
from .ontology_annotation import OntologyAnnotation
from .Table.composite_cell import CompositeCell
from .Table.composite_header import (IOType, CompositeHeader)

DataMapAux_dataHeader: CompositeHeader = CompositeHeader(11, IOType(2))

DataMapAux_explication: OntologyAnnotation = OntologyAnnotation("Clarification", "NCIT", "http://purl.obolibrary.org/obo/NCIT_C94778")

DataMapAux_explicationHeader: CompositeHeader = CompositeHeader(3, DataMapAux_explication)

DataMapAux_unit: OntologyAnnotation = OntologyAnnotation("Unit", "UO", "http://purl.obolibrary.org/obo/UO_0000000")

DataMapAux_unitHeader: CompositeHeader = CompositeHeader(3, DataMapAux_unit)

DataMapAux_objectType: OntologyAnnotation = OntologyAnnotation("Data Type", "NCIT", "http://purl.obolibrary.org/obo/NCIT_C42645")

DataMapAux_objectTypeHeader: CompositeHeader = CompositeHeader(3, DataMapAux_objectType)

DataMapAux_labelHeader: CompositeHeader = CompositeHeader(13, "Label")

DataMapAux_descriptionHeader: CompositeHeader = CompositeHeader(13, "Description")

DataMapAux_generatedByHeader: CompositeHeader = CompositeHeader(13, "Generated By")

DataMapAux_allowedHeaders: FSharpList[CompositeHeader] = of_array([DataMapAux_dataHeader, DataMapAux_explicationHeader, DataMapAux_unitHeader, DataMapAux_objectTypeHeader, DataMapAux_descriptionHeader, DataMapAux_generatedByHeader])

def DataMapAux_getOntologyColumn(f: Callable[[DataContext], OntologyAnnotation | None], data_contexts: Array[DataContext]) -> Array[CompositeCell]:
    def mapping(dc: DataContext, f: Any=f, data_contexts: Any=data_contexts) -> CompositeCell:
        match_value: OntologyAnnotation | None = f(dc)
        if match_value is None:
            return CompositeCell.empty_term()

        else: 
            return CompositeCell(0, match_value)


    return list(map(mapping, data_contexts))


def DataMapAux_getStringColumn(f: Callable[[DataContext], str | None], data_contexts: Array[DataContext]) -> Array[CompositeCell]:
    def mapping(dc: DataContext, f: Any=f, data_contexts: Any=data_contexts) -> CompositeCell:
        match_value: str | None = f(dc)
        if match_value is None:
            return CompositeCell.empty_free_text()

        else: 
            return CompositeCell(1, match_value)


    return list(map(mapping, data_contexts))


def DataMapAux_setOntologyColumn(f: Callable[[DataContext, OntologyAnnotation | None], None], column: Array[CompositeCell], data_contexts: Array[DataContext]) -> None:
    def action(i: int, cell: CompositeCell, f: Any=f, column: Any=column, data_contexts: Any=data_contexts) -> None:
        if cell.tag == 0:
            f(data_contexts[i], cell.fields[0])


    iterate_indexed(action, column)


def DataMapAux_setStringColumn(f: Callable[[DataContext, str | None], None], column: Array[CompositeCell], data_contexts: Array[DataContext]) -> None:
    def action(i: int, cell: CompositeCell, f: Any=f, column: Any=column, data_contexts: Any=data_contexts) -> None:
        if cell.tag == 1:
            f(data_contexts[i], cell.fields[0])


    iterate_indexed(action, column)


def DataMapAux_SanityChecks_rowIndexInBoundaries(row: int, data_contexts: Array[DataContext]) -> None:
    if row < 0:
        raise Exception("Row index must be greater or equal to 0.")

    if row >= len(data_contexts):
        raise Exception("Row index must be less than the number of rows.")



def DataMapAux_SanityChecks_lengthOfNewColumn(new_column: Array[CompositeCell], data_contexts: Array[DataContext]) -> None:
    if len(new_column) != len(data_contexts):
        raise Exception("Length of new column does not match length of data contexts.")



def _expr887() -> TypeInfo:
    return class_type("ARCtrl.DataMap", None, DataMap)


class DataMap:
    def __init__(self, data_contexts: Array[DataContext]) -> None:
        self.static_hash: int = 0
        self.data_contexts_0040108: Array[DataContext] = data_contexts

    @property
    def StaticHash(self, __unit: None=None) -> int:
        this: DataMap = self
        return this.static_hash

    @StaticHash.setter
    def StaticHash(self, value: int) -> None:
        this: DataMap = self
        this.static_hash = value or 0

    @property
    def DataContexts(self, __unit: None=None) -> Array[DataContext]:
        this: DataMap = self
        return this.data_contexts_0040108

    @staticmethod
    def init(__unit: None=None) -> DataMap:
        return DataMap([])

    def GetExplicationColumn(self, __unit: None=None) -> Array[CompositeCell]:
        this: DataMap = self
        return DataMapAux_getOntologyColumn(DataContext__get_Explication, this.data_contexts_0040108)

    def SetExplicationColumn(self, cells: Array[CompositeCell]) -> None:
        this: DataMap = self
        def _arrow880(dc: DataContext, oa: OntologyAnnotation | None=None) -> None:
            DataContext__set_Explication_279AAFF2(dc, oa)

        DataMapAux_setOntologyColumn(_arrow880, cells, this.data_contexts_0040108)

    def GetUnitColumn(self, __unit: None=None) -> Array[CompositeCell]:
        this: DataMap = self
        return DataMapAux_getOntologyColumn(DataContext__get_Unit, this.data_contexts_0040108)

    def SetUnitColumn(self, cells: Array[CompositeCell]) -> None:
        this: DataMap = self
        def _arrow881(dc: DataContext, oa: OntologyAnnotation | None=None) -> None:
            DataContext__set_Unit_279AAFF2(dc, oa)

        DataMapAux_setOntologyColumn(_arrow881, cells, this.data_contexts_0040108)

    def GetObjectTypeColumn(self, __unit: None=None) -> Array[CompositeCell]:
        this: DataMap = self
        return DataMapAux_getOntologyColumn(DataContext__get_ObjectType, this.data_contexts_0040108)

    def SetDataTypeColumn(self, cells: Array[CompositeCell]) -> None:
        this: DataMap = self
        def _arrow882(dc: DataContext, oa: OntologyAnnotation | None=None) -> None:
            DataContext__set_ObjectType_279AAFF2(dc, oa)

        DataMapAux_setOntologyColumn(_arrow882, cells, this.data_contexts_0040108)

    def GetLabelColumn(self, __unit: None=None) -> Array[CompositeCell]:
        this: DataMap = self
        def _arrow883(dc: DataContext) -> str | None:
            return dc.Name

        return DataMapAux_getStringColumn(_arrow883, this.data_contexts_0040108)

    def SetLabelColumn(self, cells: Array[CompositeCell]) -> None:
        this: DataMap = self
        def _arrow884(dc: DataContext, s: str | None=None) -> None:
            dc.Name = s

        DataMapAux_setStringColumn(_arrow884, cells, this.data_contexts_0040108)

    def GetDescriptionColumn(self, __unit: None=None) -> Array[CompositeCell]:
        this: DataMap = self
        return DataMapAux_getStringColumn(DataContext__get_Description, this.data_contexts_0040108)

    def SetDescriptionColumn(self, cells: Array[CompositeCell]) -> None:
        this: DataMap = self
        def _arrow885(dc: DataContext, s: str | None=None) -> None:
            DataContext__set_Description_6DFDD678(dc, s)

        DataMapAux_setStringColumn(_arrow885, cells, this.data_contexts_0040108)

    def GetDataContext(self, row: int, SkipValidation: Any | None=None) -> DataContext:
        this: DataMap = self
        DataMapAux_SanityChecks_rowIndexInBoundaries(row, this.data_contexts_0040108)
        return this.data_contexts_0040108[row]

    @staticmethod
    def get_data_context(row: int, SkipValidation: Any | None=None) -> Callable[[DataMap], DataContext]:
        def _arrow886(dm: DataMap) -> DataContext:
            return dm.GetDataContext(row, SkipValidation)

        return _arrow886

    def Copy(self, __unit: None=None) -> DataMap:
        this: DataMap = self
        return DataMap(list(map(DataContext__Copy, this.data_contexts_0040108)))

    def __eq__(self, obj: Any=None) -> bool:
        this: DataMap = self
        return hash_1(this) == hash_1(obj)

    def __hash__(self, __unit: None=None) -> Any:
        this: DataMap = self
        return box_hash_seq(this.data_contexts_0040108)

    @staticmethod
    def FileName() -> str:
        return "isa.datamap.xlsx"


DataMap_reflection = _expr887

def DataMap__ctor_4E3220A7(data_contexts: Array[DataContext]) -> DataMap:
    return DataMap(data_contexts)


__all__ = ["DataMapAux_dataHeader", "DataMapAux_explication", "DataMapAux_explicationHeader", "DataMapAux_unit", "DataMapAux_unitHeader", "DataMapAux_objectType", "DataMapAux_objectTypeHeader", "DataMapAux_labelHeader", "DataMapAux_descriptionHeader", "DataMapAux_generatedByHeader", "DataMapAux_allowedHeaders", "DataMapAux_getOntologyColumn", "DataMapAux_getStringColumn", "DataMapAux_setOntologyColumn", "DataMapAux_setStringColumn", "DataMapAux_SanityChecks_rowIndexInBoundaries", "DataMapAux_SanityChecks_lengthOfNewColumn", "DataMap_reflection"]

