"""Utility functions that are used in multiple modules"""
import pandas as pd
import logging

LOGGER = logging.getLogger(__name__)


def listify(obj):
    """Create list containing an object if it is not already a list."""
    try:
        assert not isinstance(obj, str)
        iter(obj)
    except (AssertionError, TypeError):
        obj = [obj]

    return list(obj)


def new_column(name, df):
    """Add a new column, ensuring a unique name"""
    new_name = name
    cols = set(df.columns)
    i = 0
    while new_name in cols:
        new_name = name + "_" + str(i)
        i += 1

    return new_name


def create_pairing_from_file(pairing_file_name):
    """Parse a single file that explicity pairs target and decoy sequences.

    Parameters
    ----------
    pairing_file_name : str
        A tab-delimited file that explicity pairs target and decoy peptide
        sequences. Requires one column labled 'target' that contains target
        sequences and a second column labeled 'decoy(s)' that contains decoy
        sequences. For analying fles generated by Tide, this file can be
        generated by setting --peptide-list=T in tide-index.

    Returns
    -------
    pairing : dict
        A map of target and decoy peptide sequence pairings. Targets with
        missing decoys will not be included among the keys.

    """
    pairing_file = pd.read_csv(pairing_file_name, sep="\t")

    # ensure pairing_file dataframe contains all necessary columns
    target_field = "target"
    decoy_field = "decoy(s)"
    req_fields = [
        target_field,
        decoy_field,
    ]

    if not set(req_fields).issubset(pairing_file.columns):
        miss = ", ".join(set(req_fields) - set(pairing_file.columns))
        raise ValueError(
            f"Required columns for peptide pairing were not detected: {miss}"
        )

    # drop targets that do not have corresponding decoys
    pairing_file = pairing_file[pairing_file[decoy_field] != ""]
    return dict(zip(pairing_file[target_field], pairing_file[decoy_field]))


def parse_psms_txt(txt_file, cols, skip_line):
    """Parse a single tab-delimited file

    Parameters
    ----------
    txt_file : str
        The tab-delimited file of PSMs to read.
    cols : list of str
        The columns to parse.
    skip_line : bool
        If true, skip reading the first line.

    Returns
    -------
    pandas.DataFrame
        A :py:class:`pandas.DataFrame` containing the parsed PSMs
    """
    LOGGER.info("Reading PSMs from %s...", txt_file)

    # Because skip_line is a boolean:
    return pd.read_csv(
        txt_file,
        sep="\t",
        skiprows=int(skip_line),
        usecols=lambda c: c in cols,
    )
