import html
import re

from core.command_param_types import Any
from core.decorators import instance, command


@instance()
class CalculatorController:
    def __init__(self):
        self.allow_chars_regex = re.compile(r"^[0123456789.+\-*%()/ &|^~<>]+$")

    @command(command="calc",
             params=[Any("formula")],
             access_level="member",
             description="Perform a calculation",
             extended_description="Supported operators:\n\n"
                                  "+ (addition)\n"
                                  "- (subtraction)\n"
                                  "* (multiplication)\n"
                                  "/ (division)\n"
                                  "% (modulus)\n"
                                  "** (exponent)\n"
                                  "// (floor/integer division)\n"
                                  "< (less than)\n"
                                  "> (greater than)\n"
                                  "() (parenthesis)\n"
                                  "& (binary AND)\n"
                                  "| (binary OR)\n"
                                  "^ (binary exclusive OR)\n"
                                  "~ (binary ones complement)\n"
                                  "<< (binary left shift)\n"
                                  ">> (binary right shift)")
    def calc_cmd(self, _, formula):
        # this may be problematic if this bot is running on a system with a different locale
        formula = html.unescape(formula.replace(",", "."))
        if self.allow_chars_regex.match(formula):
            try:
                return f"{formula} = {round(eval(formula), 4)}"
            except SyntaxError:
                return "Error! Invalid formula supplied."
        else:
            return "Error! Invalid character detected."
