package top.quantic.sentry.discord;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sx.blah.discord.handle.impl.obj.Message;
import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.EmbedBuilder;
import sx.blah.discord.util.RequestBuffer;
import top.quantic.sentry.discord.core.Command;
import top.quantic.sentry.discord.core.CommandBuilder;
import top.quantic.sentry.discord.module.CommandSupplier;
import top.quantic.sentry.discord.util.DiscordUtil;
import top.quantic.sentry.service.ScriptService;
import top.quantic.sentry.service.util.Result;

import java.awt.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static top.quantic.sentry.discord.util.DiscordUtil.*;

@Component
public class Eval implements CommandSupplier {

    private static final Logger log = LoggerFactory.getLogger(Eval.class);

    private final ScriptService scriptService;

    @Autowired
    public Eval(ScriptService scriptService) {
        this.scriptService = scriptService;
    }

    @Override
    public List<Command> getCommands() {
        return Collections.singletonList(eval());
    }

    private Command eval() {
        return CommandBuilder.of("eval")
            .describedAs("Run a script")
            .in("Administrative")
            .nonParsed()
            .secured()
            .onExecute(context -> {
                IMessage message = context.getMessage();
                IChannel channel = message.getChannel();
                String withCommand = context.getContentAfterPrefix();
                String content = withCommand.contains(" ") ? withCommand.split(" ", 2)[1] : withCommand;
                if (isBlank(content)) {
                    answer(message, "Please input a script, code blocks optional");
                    return;
                }
                RequestBuffer.RequestFuture<IMessage> header = answer(message, "Running script, please wait...");
                doEval(message).whenComplete((result, error) -> {
                    EmbedBuilder builder = new EmbedBuilder()
                        .setLenient(true)
                        .withFooterIcon(message.getAuthor().getAvatarURL())
                        .withFooterText("Requested by " + withDiscriminator(message.getAuthor()))
                        .appendField("Command", content, false);
                    String response;
                    if (result.isSuccessful()) {
                        response = (String) result.getContent().get("result");
                        builder.withColor(new Color(0x00aa00));
                    } else {
                        response = (String) result.getContent().get("error");
                        builder.withColor(new Color(0xaa0000));
                    }
                    String title = result.isSuccessful() ? "Response" : "Error";
                    if (response.length() > Message.MAX_MESSAGE_LENGTH) {
                        String msg = "Response too long";
                        if (!channel.isPrivate()) {
                            msg += ", check your PMs!";
                        }
                        sendMessage(channel, builder.appendField(title, msg, false).build()).get();
                        answerPrivately(message, response).get();
                    } else {
                        sendMessage(channel, builder.appendField(title, response, false).build()).get();
                    }
                    CompletableFuture.supplyAsync(header::get).thenApply(DiscordUtil::deleteMessage);
                });
            })
            .build();
    }

    private CompletableFuture<Result<Map<String, Object>>> doEval(IMessage message) {
        String script = message.getContent().split(" ", 2)[1];
        script = script.replace("`", "");
        return scriptService.executeScript(script, message)
            .handle((result, error) -> {
                log.debug("eval result: {}", result);
                if (result.containsKey("error")) {
                    return Result.error(result, "Could not execute script", (Throwable) result.get("throwable"));
                } else {
                    return Result.ok(result, "Script executed successfully");
                }
            });
    }
}

@@ -682,16 +682,66 @@
 ervice;%0A
+import top.quantic.sentry.service.SettingService;%0A
 import t
@@ -1225,16 +1225,65 @@
 Service;
+%0A    private final SettingService settingService;
 %0A%0A    @A
@@ -1334,16 +1334,47 @@
 tService
+, SettingService settingService
 ) %7B%0A    
@@ -1409,24 +1409,70 @@
 iptService;%0A
+        this.settingService = settingService;%0A
     %7D%0A%0A    @
@@ -1903,27 +1903,49 @@
 l = 
-message.getChannel(
+getTrustedChannel(settingService, message
 );%0A 
@@ -1966,27 +1966,23 @@
  String 
-withCommand
+content
  = conte
@@ -2003,121 +2003,17 @@
 fter
-Prefix();%0A                String content = withCommand.contains(%22 %22) ? withCommand.split(%22 %22, 2)%5B1%5D : with
 Command
+()
 ;%0A  
@@ -3284,200 +3284,8 @@
 ) %7B%0A
-                        String msg = %22Response too long%22;%0A                        if (!channel.isPrivate()) %7B%0A                            msg += %22, check your PMs!%22;%0A                        %7D%0A
     
@@ -3356,11 +3356,27 @@
 le, 
-msg
+%22Response too long%22
 , fa
@@ -3424,31 +3424,27 @@
     
-answerPrivately(message
+sendMessage(channel
 , re

Switch to trusted channel reply