from datetime import datetime
from datetime import timedelta
import pandas as pd

def datetime_str_to_datetime(datetime_str):
    """
    This converts the strings generated when matlab datetimes are written to a table to python datetime objects
    """
    if len(datetime_str) == 24: # Check for milliseconds
        return datetime.strptime(datetime_str, '%d-%b-%Y %H:%M:%S.%f')
    else:
        return datetime.strptime(datetime_str, '%d-%b-%Y %H:%M:%S')

def well_row_letter_to_number(letter):
    """
    Converts the letter corresponding to the Axis well row to the corresponding integer row number.
    Starts with A = 1
    """
    return ord(letter) - 64

def get_row_number(unit_name):
    """
    Returns the row_number corresponding to the row_number of the 
        unit specified by unit_name. Useful for filtering rows by condition.
    """
    row_num = well_row_letter_to_number(unit_name[0])
    return row_num

def get_col_number(unit_name):
    """
    Returns the col_number tuple corresponding to the column of the 
        unit specified by unit_name. Useful for filtering rows/columns by condition.
    """
    col_num = int(unit_name[1])
    return col_num

def get_row_col_number_tuple(unit_name):
    """
    Returns the (row_number, col_number) tuple corresponding to the row_number and column of the 
        unit specified by unit_name. Useful for filtering rows/columns by condition.
    """
    row_num = get_row_number(unit_name)
    col_num = get_col_number(unit_name)
    return (row_num, col_num)

def map_classic_to_lumos(cat_table, map_path, dest_path):
    """
    Converts Axion's electrode mapping system for opaque "Classic" plates to "Lumos" plates
    """
    mapping = pd.read_csv(map_path)
    for orig_str, new_str in zip(mapping['CytoView Well / Electrode'], mapping['48 Well Classic Well / Electrode']):
        cat_table['unit_name'] = cat_table['unit_name'].str.replace(orig_str, new_str)
    cat_table['unit_name'] = cat_table['unit_name'].str.replace("_", "")
    cat_table.to_csv(dest_path)
    return cat_table

def remapped_str_to_datetime(datetime_str):
    """
    This converts the strings generated when a remapped cat_table is written to a table to python datetime objects
    """
    return datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S')

def create_stim_starts(stim_times):
    """
    Adds the date and seconds columns of the stim_times table, and returns a datetime series of the
    stimulation tags
    """
    stim_times['date_time'] = stim_times['date_time'].map(datetime_str_to_datetime)
    td=stim_times['seconds'].map(lambda x: timedelta(seconds = x))
    return stim_times['date_time']+td

def get_well_number(unit_name):
    """
    Returns the well number corresponding to the unit specified by unit_name. "A1" is well 1, "B1" is well 2, "A2" is well 7,
        etc.
    """
    (row, col) = get_row_col_number_tuple(unit_name)
    return ((col - 1)*6 + row)

def get_electrode_number(unit_name):
    """
    Returns the electrode number corresponding to the unit specified by unit_name. "A111" is electrode 1, "A121" is electrode 2, 
        "A112" is electrode 5, "B111" is electrode 17, "A211" is electrode 97, etc.
    """
    well = get_well_number(unit_name)
    return ((well-1)*16 + (int(unit_name[2])-1)*4 + int(unit_name[3]))

def get_ele_row_col_number_tuple(unit_name):
    """
    Returns the (row_number, col_number) tuple corresponding to the row_number and column of the 
        electrode specified by unit_name.
    """
    row = int(unit_name[3])
    col = int(unit_name[2])
    return (row, col)
