# functions to load the data generated by the plate reader
# and to parse the annotation file
import pandas as pd
import numpy as np
import om_code.omerrors as errors
from om_code.analyseTecan import analyseTecan
from om_code.analyseOldTecan import analyseOldTecan
from om_code.analyseSunrise import analyseSunrise


def loadfromplate(
    platereadertype, wdirpath, dname, dsheetnumber, aname, asheetnumber
):
    """Create dataframe from input files generated by the plate reader."""
    experiment = dname.split(".")[0]

    # import and process plate contents file
    allconditions, allstrains, alldata, rcontents = analyseContentsofWells(
        wdirpath, experiment, aname, asheetnumber
    )

    # import data created by plate reader
    try:
        print("loading", dname)
        dfd = pd.read_excel(str(wdirpath / dname), sheet_name=dsheetnumber)
    except FileNotFoundError:
        raise errors.FileNotFound(str(wdirpath / dname))

    # extract data from the plate reader file
    if platereadertype == "Tecan":
        rdict, datatypes = analyseTecan(dfd, rcontents, experiment)
    elif platereadertype == "old Tecan":
        rdict, datatypes = analyseOldTecan(dfd, rcontents, experiment)
    elif platereadertype == "Sunrise":
        rdict, datatypes = analyseSunrise(dfd, rcontents, experiment)
    else:
        raise errors.UnknownPlateReader(platereadertype)
    rdict = pd.DataFrame(rdict)
    datatypes = list(datatypes)
    # return dataframes for raw and processed data, error
    return rdict, allconditions, allstrains, alldata, experiment, datatypes


###


def analyseContentsofWells(wdirpath, experiment, aname, asheetnumber):
    """
    Load and parse ContentsofWells file.

    Returns rcontents, a dictionary with the contents of each well indexed
    by well, and alldata, a dictionary describing the contents of each well
    indexed by experiment.
    """
    import re

    try:
        alldata = {}
        # import contents of the wells
        anno = pd.read_excel(
            str(wdirpath / aname), index_col=0, sheet_name=asheetnumber
        )
        alldata[experiment] = []
        rcontents = {}
        # run through and parse content of each well
        for x in np.arange(1, 13):
            for y in "ABCDEFGH":
                well = y + str(x)
                if (
                    isinstance(anno[x][y], str)
                    and anno[x][y] != "contaminated"
                ):
                    s, c = anno[x][y].split(" in ")
                    # standardise naming of wells with no strains
                    s = re.sub("(null|NULL)", "Null", s)
                    rcontents[well] = [c.strip(), s.strip()]
                    alldata[experiment].append(
                        rcontents[well][1] + " in " + rcontents[well][0]
                    )
                else:
                    rcontents[well] = [None, None]
        # create summary descriptions of the well contents
        alldata[experiment] = list(np.unique(alldata[experiment]))
        allconditions = list(
            np.unique(
                [
                    rcontents[well][0]
                    for well in rcontents
                    if rcontents[well][0] is not None
                ]
            )
        )
        allstrains = list(
            np.unique(
                [
                    rcontents[well][1]
                    for well in rcontents
                    if rcontents[well][0] is not None
                ]
            )
        )
        return allconditions, allstrains, alldata, rcontents
    except FileNotFoundError:
        raise errors.FileNotFound(str(wdirpath / aname))
