"""Resource configuration module for the histopath simulation model."""
import typing as ty
import pandas as pd
import pydantic as pyd
from annotated_types import Annotated, Len
from openpyxl import Workbook
from .. import excel
[docs]
class ResourceSchedule(pyd.BaseModel):
    """A resource allocation schedule."""
    day_flags: Annotated[ty.Sequence[bool], Len(7, 7)]
    """True/1 if resource is scheduled for the day (MON to SUN), False/0 otherwise."""
    allocation: Annotated[ty.Sequence[pyd.NonNegativeInt], Len(48, 48)]
    """Number of resource units allocated for the day (in 30-min intervals),
    if the corresponding day flag is set to 1. The list length is expected to be 48."""
[docs]
    @staticmethod
    def from_pd(df: pd.DataFrame, row_name: str) -> 'ResourceSchedule':
        """Construct a resource schedule from a DataFrame row.
        Args:
            df:
                The dataframe containing the resource allocation information.
            row_name:
                The name of the resource, matching a row index in the inputted dataframe.
        """
        return __class__(
            day_flags=df.loc[row_name, 'MON':'SUN'].tolist(),
            allocation=df.loc[row_name, '00:00':'23:30'].tolist()
        ) 
 
[docs]
class ResourceInfo(pyd.BaseModel):
    """Contains information about a resource."""
    name: str
    """The name of the resource, e.g. "Scanning machine"."""
    type: ty.Literal['staff', 'machine']
    """Whether the resource is a staff or machine resource."""
    schedule: ResourceSchedule
    """A schedule defining the number of allocated resource units over the course of a week.""" 
[docs]
class ResourcesInfo(pyd.BaseModel):
    """Dataclass for tracking the staff resources of a model.
    The fields in this dataclass **MUST** match the rows of the configuration
    Excel template ("Resources" tab), with all letters to lowercase, spaces to
    underscores, and other characters removed."""
    booking_in_staff: ResourceInfo =\
        
pyd.Field(title='Booking-in staff', json_schema_extra={'resource_type': 'staff'})
    bms: ResourceInfo =\
        
pyd.Field(title='BMS', json_schema_extra={'resource_type': 'staff'})
    cut_up_assistant: ResourceInfo =\
        
pyd.Field(title='Cut-up assistant', json_schema_extra={'resource_type': 'staff'})
    processing_room_staff: ResourceInfo =\
        
pyd.Field(title='Processing room staff', json_schema_extra={'resource_type': 'staff'})
    microtomy_staff: ResourceInfo =\
        
pyd.Field(title='Microtomy staff', json_schema_extra={'resource_type': 'staff'})
    staining_staff: ResourceInfo =\
        
pyd.Field(title='Staining staff', json_schema_extra={'resource_type': 'staff'})
    scanning_staff: ResourceInfo =\
        
pyd.Field(title='Scanning staff', json_schema_extra={'resource_type': 'staff'})
    qc_staff: ResourceInfo =\
        
pyd.Field(title='QC staff', json_schema_extra={'resource_type': 'staff'})
    histopathologist: ResourceInfo =\
        
pyd.Field(title='Histopathologist', json_schema_extra={'resource_type': 'staff'})
    bone_station: ResourceInfo =\
        
pyd.Field(title='Bone station', json_schema_extra={'resource_type': 'machine'})
    processing_machine: ResourceInfo =\
        
pyd.Field(title='Processing machine', json_schema_extra={'resource_type': 'machine'})
    staining_machine: ResourceInfo =\
        
pyd.Field(title='Staining machine', json_schema_extra={'resource_type': 'machine'})
    coverslip_machine: ResourceInfo =\
        
pyd.Field(title='Coverslip machine', json_schema_extra={'resource_type': 'machine'})
    scanning_machine_regular: ResourceInfo = pyd.Field(
        title='Scanning machine (regular)', json_schema_extra={'resource_type': 'machine'})
    scanning_machine_megas: ResourceInfo = pyd.Field(
        title='Scanning machine (megas)', json_schema_extra={'resource_type': 'machine'})
[docs]
    @staticmethod
    def from_workbook(wbook: Workbook) -> 'ResourcesInfo':
        """Construct a dataclass instance from an Excel workbook.
        Args:
            wbook: The Excel workbook to parse.
        Returns:
            The parsed dataclass instance.
        """
        resources_df = (
            pd.DataFrame(
                (
                    table := excel.get_table(wbook, 'Resource Allocation', 'Resources')
                )[1:],
                columns=table[0]
            )
            .fillna(0.)
            .set_index('Resource')
        )
        return ResourcesInfo.model_validate({
            key: ResourceInfo(
                name=field.title,
                type=field.json_schema_extra['resource_type'],
                schedule=ResourceSchedule.from_pd(resources_df, row_name=field.title)
            )
            for key, field in ResourcesInfo.model_fields.items()
        })