import pandas as pd
import os
from appia.processors.core import normalizer, loading_bar

def append_fplc(file_list, cv = 24):
    if isinstance(file_list, str):
        file_list = [file_list]

    chroms = pd.DataFrame(columns = ['mL', 'CV', 'Channel', 'Signal', 'Fraction', 'Sample'])
    for i in range(len(file_list)):

        loading_bar(i+1, (len(file_list)), extension = ' AKTA files')
        file = file_list[i]

        try:
            fplc_trace = pd.read_csv(
                file, skiprows = 1,
                header = [1],
                encoding = 'utf-16-le',
                delimiter = '\t',
                engine = 'python'
            )
        except UnicodeDecodeError:
            fplc_trace = pd.read_csv(
                file, skiprows = 1,
                header = [1],
                encoding = 'utf-8',
                delimiter = ',',
                engine = 'python'
            )

        # The AKTA exports data with several different ml columns, each with their
        # own name (like ml.2, ml.3, etc.). These are mL axes for each channel.
        # Unfortunately, they are different for each channel! So we need to keep
        # each and know which channel it goes with. Additionally, since users
        # don't have to export every channel every time, we can't hard code positions
        
        fplc_trace = fplc_trace.filter(regex = '(ml|mAU$|mS/cm$|\%$|Fraction)')
        columns = fplc_trace.columns
        renaming = {}
        for col_name in ['mAU', 'mS/cm', '%', 'Fraction']:
            if col_name in columns:
                column = columns.get_loc(col_name)
                renaming[columns[column-1]] = f'mL_{col_name}'

        fplc_trace = fplc_trace.rename(columns = renaming)

        channels = []
        for column in ['mAU', 'mS/cm', '%']:
            channel = pd.melt(
                fplc_trace,
                id_vars = [f'mL_{column}'],
                value_vars = [column],
                var_name = 'Channel',
                value_name = 'Signal')
            channel = channel.rename(columns = {f'mL_{column}':'mL'}).dropna()
            channels.append(channel)
        long_trace = pd.concat(channels, ignore_index=True)

        long_trace['Fraction'] = 1
        frac_mL = fplc_trace['mL_Fraction'].dropna()
        for i in range(len(frac_mL)):
            # The +2 here is a magic number. For whatever reason, the fractions
            # generated by this method were off by two from those displayed in
            # the AKTA software. And since those are where your protein actually
            # ends up, it's pretty important that everything matches.
            long_trace.loc[long_trace['mL'] > frac_mL[i], 'Fraction'] = i + 2

        long_trace['CV'] = long_trace['mL']/cv

        chroms = pd.concat([chroms, long_trace], ignore_index = True)
        chroms.Sample = os.path.split(file)[1][:-4]
        chroms = chroms.loc[(chroms.CV >= 0) & (chroms.CV <=1)]

        chroms = chroms.groupby(['Channel'], group_keys=False).apply(normalizer)
        chroms = chroms.melt(
            id_vars = ['mL', 'CV', 'Channel', 'Fraction', 'Sample'],
            value_vars = ['Signal', 'Normalized'],
            var_name = 'Normalization',
            value_name = 'Value'
        )

        return chroms