package hello;

import hello.torrent.Premiumize;
import hello.torrent.Torrent;
import hello.torrent.TorrentHelper;
import hello.torrent.TorrentSearchEngine;
import hello.torrent.TorrentSearchEngineService;
import hello.utilities.HttpHelper;
import hello.utilities.PropertiesHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotNull;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public final class BoatController {
    private final String switchToProgress = "<a href=\"../debug\">Show Progress</a> ";
    private final TorrentSearchEngineService torrentSearchEngineService;
    private final HttpHelper httpHelper;

    @Autowired
    public BoatController(TorrentSearchEngineService torrentSearchEngineService, HttpHelper httpHelper) {
        this.torrentSearchEngineService = torrentSearchEngineService;
        this.httpHelper = httpHelper;
    }

    @GetMapping({"/"})
    @NotNull
    public final String index() {
        return "Greetings from Spring Boot!";
    }

    @GetMapping({"/search"})
    @NotNull
    public final String search() {
        return "<!DOCTYPE html>\n" +
                "<html>\n" +
                "<body>\n" +
                "\n" +
                "<h2>Here to serve you</h2>\n" +
                "\n" +
                "<form action=\"../boat\" target=\"_blank\" method=\"GET\">\n" +
                "  Title:<br>\n" +
                "  <input type=\"text\" name=\"q\" value=\"\">\n" +
                "  <br>\n" +
                "  <input type=\"submit\" value=\"Search\">\n" +
                "</form>\n" +
                "  <br>\n" +
                "  <br>\n" +
                "<form action=\"../boat/download\" target=\"_blank\" method=\"POST\">\n" +
                "  Direct download URL:<br>\n" +
                "  <input type=\"text\" name=\"dd\" value=\"\">\n" +
                "  <br>\n" +
                "  <input type=\"submit\" value=\"Download\">\n" +
                "</form>\n" +
                "<br/>\n" +
                switchToProgress.replace("..", "../boat") +
                "</body>\n" +
                "</html>\n";
    }

    @GetMapping({"/boat"})
    @NotNull
    public final String getTorrents(@RequestParam("q") @NotNull String searchString) {
        List<Torrent> combineResults = new ArrayList<>();

        long currentTimeMillis = System.currentTimeMillis();

        final List<TorrentSearchEngine> activeSearchEngines = new ArrayList<>();
        activeSearchEngines.addAll(torrentSearchEngineService.getActiveSearchEngines());
        activeSearchEngines.parallelStream()
                .forEach(torrentSearchEngine -> combineResults.addAll(torrentSearchEngine.searchTorrents(searchString)));
        List<Torrent> returnResults = new ArrayList<>(cleanDuplicates(combineResults));
        returnResults.sort(TorrentHelper.torrentSorter);

        System.out.println(String.format("Took: [%s]ms for [%s]", (System.currentTimeMillis() - currentTimeMillis), searchString));

        return "G: " + returnResults.stream().limit(25).collect(Collectors.toList());
    }

    private List<Torrent> cleanDuplicates(List<Torrent> combineResults) {
        ArrayList<Torrent> cleanedTorrents = new ArrayList<>();
        combineResults.forEach(result -> {
            if (!cleanedTorrents.contains(result)) {
                cleanedTorrents.add(result);
            }
        });
        return cleanedTorrents;
    }

    @GetMapping({"/boat/download"})
    @NotNull
    public final String downloadTorrentToPremiumize(@RequestParam("d") @NotNull String downloadUri) {
        byte[] magnetUri = Base64.getUrlDecoder().decode(downloadUri);
        String decodedUri = new String(magnetUri, StandardCharsets.UTF_8);
        Torrent torrentToBeDownloaded = new Torrent();
        torrentToBeDownloaded.magnetUri = decodedUri;
        return switchToProgress + (new Premiumize(httpHelper)).addTorrentToQueue(torrentToBeDownloaded);
    }

    @GetMapping({"/boat/download"})
    @NotNull
    public final String directDownloadTorrentToPremiumize(@RequestParam("dd") @NotNull String downloadUri) {
        Torrent torrentToBeDownloaded = new Torrent();
        torrentToBeDownloaded.magnetUri = downloadUri;
        return switchToProgress + (new Premiumize(httpHelper)).addTorrentToQueue(torrentToBeDownloaded);
    }

    @GetMapping({"/boat/debug"})
    @NotNull
    public final String getDebugInfo() {
        ArrayList<Torrent> remoteTorrents = new Premiumize(httpHelper).getRemoteTorrents();
        return "v:" + PropertiesHelper.getVersion() + "<br/>ActiveSearchEngines: " + torrentSearchEngineService.getActiveSearchEngines() + "<br/>D: " + remoteTorrents;
    }

    @GetMapping({"/boat/shutdown"})
    @NotNull
    public final void shutdownServer() {
        System.exit(0);
    }
}

@@ -271,24 +271,70 @@
 tiesHelper;%0A
+import org.apache.logging.log4j.util.Strings;%0A
 import org.s
@@ -3923,29 +3923,195 @@
 ram(
-%22d%22) @NotNull String 
+value = %22d%22, required = false) String downloadUri, @RequestParam(value = %22dd%22, required = false) String directDownloadUri) %7B%0A        String decodedUri = %22%22;%0A        if(Strings.isNotEmpty(
 down
@@ -4110,35 +4110,40 @@
 pty(downloadUri)
+)
  %7B%0A
+    
         byte%5B%5D m
@@ -4197,38 +4197,35 @@
 adUri);%0A        
-String
+   
  decodedUri = ne
@@ -4281,209 +4281,51 @@
     
-Torrent torrentToBeDownloaded = new Torrent();%0A        torrentToBeDownloaded.magnetUri = decodedUri;%0A        return switchToProgress + (new Premiumize(httpHelper)).addTorrentToQueue(torrentToBe
+%7D else if(Strings.isNotEmpty(direct
 Download
 ed);
@@ -4324,177 +4324,68 @@
 load
-ed);
+Uri))%7B
 %0A    
-%7D%0A%0A
     
-@GetMapping(%7B%22/boat/download%22%7D)%0A    @NotNull%0A    public final String directDownloadTorrentToPremiumize(@RequestParam(%22dd%22) @NotNull String downloadUri) %7B
+    decodedUri = directDownloadUri;%0A        %7D
 %0A   
@@ -4479,22 +4479,21 @@
 tUri = d
-ownloa
+ecode
 dUri;%0A  

fix controller method