import random
import time

from core.command_param_types import Any, Int, Const
from core.db import DB
from core.decorators import instance, command


# noinspection SqlInsertValues
@instance()
class RandomController:
    def inject(self, registry):
        self.db: DB = registry.get_instance("db")
        self.util = registry.get_instance("util")
        self.character_service = registry.get_instance("character_service")
        self.command_alias_service = registry.get_instance("command_alias_service")

    def start(self):
        self.db.exec("CREATE TABLE IF NOT EXISTS roll (id INT PRIMARY KEY AUTO_INCREMENT, "
                     "created_at INT NOT NULL, "
                     "char_id INT NOT NULL, "
                     "options VARCHAR(2048), "
                     "result VARCHAR(255))")
        self.db.create_view("roll")
        self.command_alias_service.add_alias("verify", "roll verify")
        self.command_alias_service.add_alias("lootorder", "random")

    @command(command="random", params=[Any("items")], access_level="member",
             description="Randomly order a list of elements",
             extended_description="Enter a space-delimited list of items to randomize.")
    def random_command(self, _, items):
        items = items.split(" ")
        random.shuffle(items)
        return " ".join(items)

    @command(command="roll", params=[Const("verify"), Int("roll_id")], access_level="member",
             description="Verify a roll that happened")
    def roll_verify_command(self, _, _1, roll_id):
        row = self.db.query_single("SELECT * FROM roll WHERE id = ?", [roll_id])
        if not row:
            return f"Could not find roll with id <highlight>{roll_id:d}</highlight>."
        else:
            time_string = self.util.time_to_readable(int(time.time()) - row.created_at)
            name = self.character_service.resolve_char_to_name(row.char_id)
            return f"<highlight>{row.result}</highlight> rolled by <highlight>{name}</highlight> " \
                   f"{time_string} ago. Possible options: {row.options}."

    @command(command="roll", params=[Int("start_value", is_optional=True), Int("end_value")], access_level="member",
             description="Roll a number between 1 and a number",
             extended_description="The given numbers are included in the roll.")
    def roll_number_command(self, request, start_value, end_value):
        start_value = start_value or 1
        if start_value > end_value:
            end = start_value
            start = end_value
        else:
            start = start_value
            end = end_value
        result = random.randint(start, end)
        options = f"value between {start:d} and {end:d}"
        self.db.exec("INSERT INTO roll (created_at, char_id, options, result) VALUES (?, ?, ?, ?)",
                     [int(time.time()), request.sender.char_id, options, result])
        return f"The roll is <highlight>{result:d}</highlight> out of values between {start:d} and {end:d}. " \
               f"To verify do /tell <myname> verify {self.db.last_insert_id():d}"

    # Keep this method at the bottom of file otherwise it will precede over all other commands
    @command(command="roll", params=[Any("items")], access_level="member",
             description="Roll a random value",
             extended_description="Enter a space-delimited list of values to roll")
    def roll_text_variables_command(self, request, items):
        options = items.split(" ")
        result = random.choice(options)
        self.db.exec("INSERT INTO roll (created_at, char_id, options, result) VALUES (?, ?, ?, ?)",
                     [int(time.time()), request.sender.char_id, items, result])
        return f"The roll is <highlight>{result}</highlight> out of possible options: {items}. " \
               f"To verify do /tell <myname> verify {self.db.last_insert_id():d}"
