/*
 * Copyright (c) 2016—2021 Andrei Tomashpolskiy and individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package bt.cli;

import bt.metainfo.TorrentFile;
import bt.torrent.fileselector.SelectionResult;
import bt.torrent.fileselector.TorrentFileSelector;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.List;
import java.util.Optional;

public class CliFileSelector extends TorrentFileSelector {
    private static final String PROMPT_MESSAGE_FORMAT = "Download '%s'? (hit <Enter> to confirm or <Esc> to skip)";
    private static final String ILLEGAL_KEYPRESS_WARNING = "*** Invalid key pressed. Please, use only <Enter> or <Esc> ***";
    private static final int EOF = -1;
    private static final int ESC = 0x1B;

    private final Optional<SessionStatePrinter> printer;
    private volatile boolean shutdown;

    public CliFileSelector() {
        this.printer = Optional.empty();
        registerShutdownHook();
    }

    public CliFileSelector(SessionStatePrinter printer) {
        this.printer = Optional.of(printer);
        registerShutdownHook();
    }

    private void registerShutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
    }

    @Override
    public List<SelectionResult> selectFiles(List<TorrentFile> files) {
        printer.ifPresent(SessionStatePrinter::pause);

        List<SelectionResult> results = super.selectFiles(files);

        printer.ifPresent(SessionStatePrinter::resume);
        return results;
    }

    @Override
    protected SelectionResult select(TorrentFile file) {
        while (!shutdown) {
            System.out.println(getPromptMessage(file));

            try {
                switch (System.in.read()) {
                    case EOF: {
                        throw new IllegalStateException("EOF");
                    }
                    case '\n': { // <Enter>
                        return SelectionResult.select().build();
                    }
                    case ESC: {
                        return SelectionResult.skip();
                    }
                    default: {
                        System.out.println(ILLEGAL_KEYPRESS_WARNING);
                    }
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        throw new IllegalStateException("Shutdown");
    }

    private static String getPromptMessage(TorrentFile file) {
        return String.format(PROMPT_MESSAGE_FORMAT, String.join("/", file.getPathElements()));
    }

    private void shutdown() {
        this.shutdown = true;
    }
}

@@ -1034,17 +1034,17 @@
  '%25s'? (
-h
+H
 it %3CEnte
@@ -1060,25 +1060,96 @@
 firm
- or %3CEsc%3E to skip
+, %3CEsc%3E to skip, %3Ca%3E to confirm all remaining, %3Cs%3E to skip all remaining or %3Cq%3E to abort
 )%22;%0A
@@ -1237,46 +1237,92 @@
 ed. 
-Please, use only %3CEnter%3E or %3CEsc%3E ***%22
+***%22;%0A    private static final int EOF = -1;%0A    private static final int ESC = 0x1B
 ;%0A  
@@ -1344,32 +1344,34 @@
 c final int 
-EOF = -1
+CTRL_C = 3
 ;%0A    privat
@@ -1389,26 +1389,26 @@
 nal int 
-ESC = 0x1B
+CTRL_D = 4
 ;%0A%0A    p
@@ -1499,16 +1499,105 @@
 tdown;%0A%0A
+    private boolean selectRemaining = false;%0A    private boolean skipRemaining = false;%0A%0A
     publ
@@ -2355,24 +2355,218 @@
 shutdown) %7B%0A
+            if (selectRemaining) %7B%0A                return SelectionResult.select().build();%0A            %7D else if (skipRemaining) %7B%0A                return SelectionResult.skip();%0A            %7D%0A%0A
             
@@ -2820,198 +2820,801 @@
 se '
-%5Cn': %7B // %3CEnter%3E%0A                        return SelectionResult.select().build();%0A                    %7D%0A                    case ESC: %7B%0A                        return SelectionResult.skip()
+a':%0A                    case 'A': %7B%0A                        selectRemaining = true;%0A                        return SelectionResult.select().build();%0A                    %7D%0A                    case '%5Cn': %7B // %3CEnter%3E%0A                        return SelectionResult.select().build();%0A                    %7D%0A                    case 's':%0A                    case 'S': %7B%0A                        skipRemaining = true;%0A                        return SelectionResult.skip();%0A                    %7D%0A                    case ESC: %7B%0A                        return SelectionResult.skip();%0A                    %7D%0A                    case CTRL_C:%0A                    case CTRL_D:%0A                    case 'q':%0A                    case 'Q': %7B%0A                        confirmAbort();%0A                        break
 ;%0A  
@@ -4178,11 +4178,467 @@
 e;%0A    %7D
+%0A%0A    private void confirmAbort() throws IOException %7B%0A        System.out.println(%22Are you sure you want to abort (y/n)?%22);%0A        switch (System.in.read()) %7B%0A            case 'y':%0A            case 'Y':%0A            case CTRL_C:%0A            case CTRL_D: %7B%0A                System.out.println(%22Aborting...%22);%0A                System.exit(0);%0A            %7D%0A            default: %7B%0A                System.out.println(%22Resuming...%22);%0A            %7D%0A        %7D%0A    %7D
 %0A%7D%0A

Add new keystrokes to CliFileSelector