# -*- coding: utf-8 -*-
"""
LemonSoap - headers scent.

Deals with column headers.
"""
import pandas as pd
import inflection
import re
import logging

from ..lemon_bar import LemonBar
from .scent_template import ScentTemplate


class ColumnsScent(ScentTemplate):
    """
    Manages headers issue identification and fixing.
    """
    def __init__(self, lf: LemonBar):
        ScentTemplate.__init__(self, lf, "headers",
                               "columns_scent.ColumnsScent")

    def check(self) -> bool:
        """
        Identifies issues with headers in a dataframe.

        Correct format is "snake_case", with no special characters. Numbers
        are however allowed.

        Returns:
            False if no issues otherwise True.
        """
        columns = self._lb().columns

        for column in columns:
            fixed = self._standardize(column)
            if fixed != column:
                self._log.info(f"* '{column}' incorrect format, "
                               f"should be '{fixed}.")

        return self._finish_check()

    def fix(self) -> LemonBar:
        """
        Fixes headers in a given LemonBar.

        Returns:
            LemonBar with fixes applied.
        """
        self.check()
        for issue in self._issues:
            # OK to call this here as well as in check as unlikely to be
            # enough headers to cause an overhead.
            fixed = self._standardize(issue[0])
            self._log.info(f"* '{issue[0]}' replaced with '{fixed}'")
            self._lb().rename(columns={issue[0]: fixed}, inplace=True)

        return self._lb

    def _standardize(self, inp: str) -> str:
        """
        Converts input to standard column header format.

        * snake_case.

        * No special characters.

        * Less than 24 characters long.

        * Unique.

        Args:
            inp: string to fix.
        Returns:
            Converted input.
        """
        # Make underscored, lower case with no special characters.
        fixed = inp.replace(" ", "_")
        fixed = inflection.underscore(fixed)
        fixed = re.sub('\W+', '', fixed)

        # Headers less than 24 chars.
        if len(fixed) > 24:
            fixed = fixed[:24]

        # If not unique then try with repeatedly incrementing numbers.
        # TODO: O(n^2) algorithm, becomes very slow with lots of headers that
        # are the same. Should use precomputation table.
        sim_num = 0
        fixed_inc = fixed
        while fixed_inc in self._lb().columns:
            sim_str = str(sim_num)
            fixed_inc = fixed + str(sim_num)
            sim_num += 1

        return fixed_inc

# -*- coding: utf-8 -*-
"""
LemonSoap - headers scent.

Deals with column headers.
"""
import pandas as pd
import inflection
import re
import logging

from ..lemon_bar import LemonBar
from .scent_template import ScentTemplate


class ColumnsScent(ScentTemplate):
    """
    Manages headers issue identification and fixing.
    """
    def __init__(self, lf: LemonBar):
        ScentTemplate.__init__(self, lf, "headers",
                               "columns_scent.ColumnsScent")

    def check(self) -> bool:
        """
        Identifies issues with headers in a dataframe.

        Correct format is "snake_case", with no special characters. Numbers
        are however allowed.

        Returns:
            False if no issues otherwise True.
        """
        columns = self._lb().columns

        for column in columns:
            fixed = self._standardize(column)
            if fixed != column:
                self._log.info(f"* '{column}' incorrect format, "
                               f"should be '{fixed}.")

        return self._finish_check()

    def fix(self) -> LemonBar:
        """
        Fixes headers in a given LemonBar.

        Returns:
            LemonBar with fixes applied.
        """
        self.check()
        for issue in self._issues:
            # OK to call this here as well as in check as unlikely to be
            # enough headers to cause an overhead.
            fixed = self._standardize(issue[0])
            self._log.info(f"* '{issue[0]}' replaced with '{fixed}'")
            self._lb().rename(columns={issue[0]: fixed}, inplace=True)

        return self._lb

    def _standardize(self, inp: str) -> str:
        """
        Converts input to standard column header format.

        * snake_case.

        * No special characters.

        * Less than 24 characters long.

        * Unique.

        Args:
            inp: string to fix.
        Returns:
            Converted input.
        """
        # Make underscored, lower case with no special characters.
        fixed = inp.replace(" ", "_")
        fixed = inflection.underscore(fixed)
        fixed = re.sub('\W+', '', fixed)

        # Headers less than 24 chars.
        if len(fixed) > 24:
            fixed = fixed[:24]

        # If not unique then try with repeatedly incrementing numbers.
        # TODO: O(n^2) algorithm, becomes very slow with lots of headers that
        # are the same. Should use precomputation table.
        sim_num = 0
        fixed_inc = fixed
        while fixed_inc in self._lb().columns:
            sim_str = str(sim_num)
            fixed_inc = fixed + str(sim_num)
            sim_num += 1

        return fixed_inc

# -*- coding: utf-8 -*- LemonSoap - headers scent.  Deals with column headers. Manages headers issue identification and fixing. Identifies issues with headers in a dataframe.          Correct format is "snake_case", with no special characters. Numbers         are however allowed.          Returns:             False if no issues otherwise True. Fixes headers in a given LemonBar.          Returns:             LemonBar with fixes applied. # OK to call this here as well as in check as unlikely to be # enough headers to cause an overhead. Converts input to standard column header format.          * snake_case.          * No special characters.          * Less than 24 characters long.          * Unique.          Args:             inp: string to fix.         Returns:             Converted input. # Make underscored, lower case with no special characters. # Headers less than 24 chars. # If not unique then try with repeatedly incrementing numbers. # TODO: O(n^2) algorithm, becomes very slow with lots of headers that # are the same. Should use precomputation table.