# See utils/checkpackagelib/readme.txt before editing this file.
# Kconfig generates errors if someone introduces a typo like "boool" instead of
# "bool", so below check functions don't need to check for things already
# checked by running "make menuconfig".

import re

from checkpackagelib.base import _CheckFunction
from checkpackagelib.lib import ConsecutiveEmptyLines  # noqa: F401
from checkpackagelib.lib import EmptyLastLine          # noqa: F401
from checkpackagelib.lib import NewlineAtEof           # noqa: F401
from checkpackagelib.lib import TrailingSpace          # noqa: F401


def _empty_or_comment(text):
    line = text.strip()
    # ignore empty lines and comment lines indented or not
    return line == "" or line.startswith("#")


def _part_of_help_text(text):
    return text.startswith("\t  ")


# used in more than one check
entries_that_should_not_be_indented = [
    "choice", "comment", "config", "endchoice", "endif", "endmenu", "if",
    "menu", "menuconfig", "source"]


class AttributesOrder(_CheckFunction):
    attributes_order_convention = {
        "bool": 1, "prompt": 1, "string": 1, "default": 2, "depends": 3,
        "select": 4, "help": 5}

    def before(self):
        self.state = 0

    def check_line(self, lineno, text):
        if _empty_or_comment(text) or _part_of_help_text(text):
            return

        attribute = text.split()[0]

        if attribute in entries_that_should_not_be_indented:
            self.state = 0
            return
        if attribute not in self.attributes_order_convention.keys():
            return
        new_state = self.attributes_order_convention[attribute]
        wrong_order = self.state > new_state

        # save to process next line
        self.state = new_state

        if wrong_order:
            return ["{}:{}: attributes order: type, default, depends on,"
                    " select, help ({}#_config_files)"
                    .format(self.filename, lineno, self.url_to_manual),
                    text]


class CommentsMenusPackagesOrder(_CheckFunction):
    def before(self):
        self.level = 0
        self.menu_of_packages = ["The top level menu"]
        self.new_package = ""
        self.package = [""]
        self.print_package_warning = [True]
        self.state = ""

    def get_level(self):
        return len(self.state.split('-')) - 1

    def initialize_package_level_elements(self, text):
        try:
            self.menu_of_packages[self.level] = text[:-1]
            self.package[self.level] = ""
            self.print_package_warning[self.level] = True
        except IndexError:
            self.menu_of_packages.append(text[:-1])
            self.package.append("")
            self.print_package_warning.append(True)

    def initialize_level_elements(self, text):
        self.level = self.get_level()
        self.initialize_package_level_elements(text)

    def check_line(self, lineno, text):
        # We only want to force sorting for the top-level menus
        if self.filename not in ["fs/Config.in",
                                 "package/Config.in",
                                 "package/Config.in.host",
                                 "package/kodi/Config.in"]:
            return

        source_line = re.match(r'^\s*source ".*/([^/]*)/Config.in(.host)?"', text)

        if text.startswith("comment "):
            if not self.state.endswith("-comment"):
                self.state += "-comment"

            self.initialize_level_elements(text)

        elif text.startswith("if "):
            self.state += "-if"

            self.initialize_level_elements(text)

        elif text.startswith("menu "):
            if self.state.endswith("-comment"):
                self.state = self.state[:-8]

            self.state += "-menu"

            self.initialize_level_elements(text)

        elif text.startswith("endif") or text.startswith("endmenu"):
            if self.state.endswith("-comment"):
                self.state = self.state[:-8]

            if text.startswith("endif"):
                self.state = self.state[:-3]

            elif text.startswith("endmenu"):
                self.state = self.state[:-5]

            self.level = self.get_level()

        elif source_line:
            self.new_package = source_line.group(1)

            # We order _ before A, so replace it with .
            new_package_ord = self.new_package.replace('_', '.')

            if self.package[self.level] != "" and \
               self.print_package_warning[self.level] and \
               new_package_ord < self.package[self.level]:
                self.print_package_warning[self.level] = False
                prefix = "{}:{}: ".format(self.filename, lineno)
                spaces = " " * len(prefix)
                return ["{prefix}Packages in: {menu},\n"
                        "{spaces}are not alphabetically ordered;\n"
                        "{spaces}correct order: '-', '_', digits, capitals, lowercase;\n"
                        "{spaces}first incorrect package: {package}"
                        .format(prefix=prefix, spaces=spaces,
                                menu=self.menu_of_packages[self.level],
                                package=self.new_package),
                        text]

            self.package[self.level] = new_package_ord


class HelpText(_CheckFunction):
    HELP_TEXT_FORMAT = re.compile(r"^\t  .{,62}$")
    URL_ONLY = re.compile(r"^(http|https|git)://\S*$")

    def before(self):
        self.help_text = False

    def check_line(self, lineno, text):
        if _empty_or_comment(text):
            return

        entry = text.split()[0]

        if entry in entries_that_should_not_be_indented:
            self.help_text = False
            return
        if text.strip() == "help":
            self.help_text = True
            return

        if not self.help_text:
            return

        if self.HELP_TEXT_FORMAT.match(text.rstrip()):
            return
        if self.URL_ONLY.match(text.strip()):
            return
        return ["{}:{}: help text: <tab><2 spaces><62 chars>"
                " ({}#writing-rules-config-in)"
                .format(self.filename, lineno, self.url_to_manual),
                text,
                "\t  " + "123456789 " * 6 + "12"]


class Indent(_CheckFunction):
    ENDS_WITH_BACKSLASH = re.compile(r"^[^#].*\\$")
    entries_that_should_be_indented = [
        "bool", "default", "depends", "help", "prompt", "select", "string"]

    def before(self):
        self.backslash = False

    def check_line(self, lineno, text):
        if _empty_or_comment(text) or _part_of_help_text(text):
            self.backslash = False
            return

        entry = text.split()[0]

        last_line_ends_in_backslash = self.backslash

        # calculate for next line
        if self.ENDS_WITH_BACKSLASH.search(text):
            self.backslash = True
        else:
            self.backslash = False

        if last_line_ends_in_backslash:
            if text.startswith("\t"):
                return
            return ["{}:{}: continuation line should be indented using tabs"
                    .format(self.filename, lineno),
                    text]

        if entry in self.entries_that_should_be_indented:
            if not text.startswith("\t{}".format(entry)):
                return ["{}:{}: should be indented with one tab"
                        " ({}#_config_files)"
                        .format(self.filename, lineno, self.url_to_manual),
                        text]
        elif entry in entries_that_should_not_be_indented:
            if not text.startswith(entry):
                # four Config.in files have a special but legitimate indentation rule
                if self.filename in ["package/Config.in",
                                     "package/Config.in.host",
                                     "package/kodi/Config.in",
                                     "package/x11r7/Config.in"]:
                    return
                return ["{}:{}: should not be indented"
                        .format(self.filename, lineno),
                        text]
