import sys

import pandas as pd

from io import StringIO
from utils.exceptions import SearchResultParsingError
from utils.search_result_parsing.helper_classes import ProteomicSearchResultReaderBaseClass, InputFile


class ScaffoldTableReader(ProteomicSearchResultReaderBaseClass):
    def __init__(self, *args, **kwargs):
        self.mandatory_style_fields = super().mandatory_style_fields + ['headline', 'eof']
        super().__init__(*args, **kwargs)

    def check_style(self):
        super().check_style()
        # style checks
        if self.style_dict['eof'] == self.style_dict['proteins_sep']:
            raise SearchResultParsingError(
                f"input style error in '{self.f_style}':\n\n"
                + f"'eof' and 'protein_sep' fields must have different content but are both:"
                + f"'{self.style_dict['proteins_sep']}'"
            )

    def read_file_into_dataframe(self):
        raw_df = self.read_scaffold_into_df()
        required_col_names = self.style_dict['sample_cols'] \
                             + [self.style_dict['proteins_col'], self.style_dict['quant_col']]
        df = raw_df[required_col_names].copy()
        del raw_df
        df['sample'] = df[self.style_dict['sample_cols']] \
            .apply(lambda x: '::'.join(map(str, x)), axis=1)

        df['proteins'] = df[self.style_dict['proteins_col']].apply(lambda x: x.split(self.style_dict['proteins_sep']))

        df_standard = pd.DataFrame()
        df_standard['proteins'] = df['proteins']
        df_standard['sample'] = df['sample']
        df_standard['quant'] = df[self.style_dict['quant_col']]

        return df_standard

    def read_scaffold_into_df(self):
        report_fname = self.result_table
        file_obj = InputFile(self.result_table)
        required_col_names = self.style_dict['headline'].split('\t')

        # process report
        print(file_obj.encoding)
        with open(report_fname, 'r', encoding=file_obj.encoding) as handle:
            data_row = False
            eof = False
            tsv_str = ""

            for line_raw in handle:
                line = line_raw.strip()

                # blank line
                if len(line) == 0:
                    continue

                # headline
                if not data_row:
                    if set(required_col_names).issubset(set(line.split('\t'))):
                        tsv_str = line_raw
                        data_row = True

                # end of file
                elif line == self.style_dict["eof"]:
                    eof = True
                    break

                # data rows
                elif data_row:
                    tsv_str += line_raw

        df = pd.read_csv(StringIO(tsv_str), sep=self.style_dict["field_sep"])
        # error checks
        if not data_row:
            sys.exit("input format error in " + report_fname + ":\nno style-specific headline")
        if not eof:
            sys.exit("input format error in " + report_fname + ":\nno style-specific eof tag")
        return df
