package com.keenwrite;
import com.keenwrite.cmdline.Arguments;
import com.keenwrite.commands.ConcatenateCommand;
import com.keenwrite.io.SysFile;
import com.keenwrite.processors.Processor;
import com.keenwrite.processors.ProcessorContext;
import com.keenwrite.processors.RBootstrapProcessor;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import static com.keenwrite.Launcher.terminate;
import static com.keenwrite.events.StatusEvent.clue;
import static com.keenwrite.io.MediaType.TEXT_R_MARKDOWN;
import static com.keenwrite.processors.ProcessorFactory.createProcessors;
import static java.nio.file.Files.readString;
import static java.nio.file.Files.writeString;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static org.apache.commons.io.FilenameUtils.getExtension;
public class AppCommands {
private static final ExecutorService sExecutor = newFixedThreadPool( 1 );
private AppCommands() {
}
public static void run( final Arguments args ) {
final var exitCode = new AtomicInteger();
final var future = new CompletableFuture<Path>() {
@Override
public boolean complete( final Path path ) {
return super.complete( path );
}
@Override
public boolean completeExceptionally( final Throwable ex ) {
clue( ex );
exitCode.set( 1 );
return super.completeExceptionally( ex );
}
};
file_export( args, future );
sExecutor.shutdown();
future.join();
terminate( exitCode.get() );
}
@SuppressWarnings( "UnusedReturnValue" )
private static Future<Path> file_export(
final Arguments args, final CompletableFuture<Path> future ) {
assert args != null;
assert future != null;
final Callable<Path> callableTask = () -> {
try {
final var context = args.createProcessorContext();
final var outputPath = context.getTargetPath();
final var chain = createProcessors( context );
final var processor = createBootstrapProcessor( chain, context );
final var inputDoc = read( context );
final var outputDoc = processor.apply( inputDoc );
final var result =
outputDoc == null ? null : writeString( outputPath, outputDoc );
future.complete( outputPath );
return result;
} catch( final Throwable ex ) {
future.completeExceptionally( ex );
return null;
}
};
return sExecutor.submit( callableTask );
}
private static Processor<String> createBootstrapProcessor(
final Processor<String> chain, final ProcessorContext context ) {
return context.getSourceType() == TEXT_R_MARKDOWN
? new RBootstrapProcessor( chain, context )
: chain;
}
private static String read( final ProcessorContext context )
throws IOException {
final var concat = context.getConcatenate();
final var inputPath = context.getSourcePath();
final var parent = inputPath.getParent();
final var filename = SysFile.getFileName( inputPath );
final var extension = getExtension( filename );
if( !concat || parent == null || extension.isBlank() ) {
return readString( inputPath );
}
final var command = new ConcatenateCommand(
parent, extension, context.getChapters() );
return command.call();
}
}