package eu.modernmt.cli;

import eu.modernmt.io.*;
import eu.modernmt.lang.Language;
import eu.modernmt.lang.LanguageDirection;
import eu.modernmt.model.Sentence;
import eu.modernmt.processing.Preprocessor;
import eu.modernmt.processing.ProcessingException;
import org.apache.commons.cli.*;
import org.apache.commons.io.IOUtils;

import java.io.Closeable;
import java.io.IOException;

/**
 * Created by davide on 17/12/15.
 */
public class PreprocessorMain {

    private static class Args {

        private static final Options cliOptions;

        static {
            Option sourceLanguage = Option.builder("s").hasArg().required().build();
            Option targetLanguage = Option.builder("t").hasArg().required().build();
            Option batch = Option.builder("b").longOpt("batch").hasArg(false).required(false).build();
            Option skipTags = Option.builder().longOpt("no-tags").hasArg(false).required(false).build();
            Option skipPlaceholders = Option.builder().longOpt("print-placeholders").hasArg(false).required(false).build();
            Option keepSpaces = Option.builder().longOpt("original-spacing").hasArg(false).required(false).build();

            cliOptions = new Options();
            cliOptions.addOption(sourceLanguage);
            cliOptions.addOption(targetLanguage);
            cliOptions.addOption(batch);
            cliOptions.addOption(skipTags);
            cliOptions.addOption(skipPlaceholders);
            cliOptions.addOption(keepSpaces);
        }

        public final LanguageDirection language;
        public final boolean printTags;
        public final boolean printPlaceholders;
        public final boolean keepSpaces;
        public final boolean batch;

        public Args(String[] args) throws ParseException {
            CommandLineParser parser = new DefaultParser();
            CommandLine cli = parser.parse(cliOptions, args);

            Language source = Language.fromString(cli.getOptionValue("s"));
            Language target = Language.fromString(cli.getOptionValue("t"));
            language = new LanguageDirection(source, target);
            printTags = !cli.hasOption("no-tags");
            printPlaceholders = cli.hasOption("print-placeholders");
            keepSpaces = cli.hasOption("original-spacing");
            batch = cli.hasOption("batch");
        }

    }

    public static void main(String[] _args) throws Throwable {
        Args args = new Args(_args);

        Preprocessor preprocessor = null;
        Outputter output = null;

        LineReader input = new UnixLineReader(System.in, UTF8Charset.get());

        try {
            preprocessor = new Preprocessor();

            if (args.keepSpaces)
                output = new SentenceOutputter(args.printTags, args.printPlaceholders);
            else
                output = new TokensOutputter(args.printTags, args.printPlaceholders);

            if (args.batch)
                batchPreprocess(preprocessor, args.language, input, output);
            else
                interactivePreprocess(preprocessor, args.language, input, output);
        } finally {
            IOUtils.closeQuietly(preprocessor);
            IOUtils.closeQuietly(output);
        }
    }

    private static void interactivePreprocess(Preprocessor preprocessor, LanguageDirection language, LineReader input, Outputter output) throws IOException, ProcessingException {
        String line;
        while ((line = input.readLine()) != null) {
            Sentence sentence = preprocessor.process(language, line);
            output.write(sentence);
        }
    }

    private static void batchPreprocess(Preprocessor preprocessor, LanguageDirection language, LineReader input, Outputter output) throws IOException, ProcessingException {
        BufferedLineReader bufferedReader = new BufferedLineReader(input);

        String[] batch;
        while ((batch = bufferedReader.readLines()) != null) {
            Sentence[] tokenized = preprocessor.process(language, batch);
            for (Sentence sentence : tokenized)
                output.write(sentence);
        }
    }

    private interface Outputter extends Closeable {

        void write(Sentence value) throws IOException;

    }

    private static class SentenceOutputter implements Outputter {

        private final UnixLineWriter writer;
        private final boolean printTags;
        private final boolean printPlaceholders;

        public SentenceOutputter(boolean printTags, boolean printPlaceholders) {
            this.writer = new UnixLineWriter(System.out, UTF8Charset.get());
            this.printTags = printTags;
            this.printPlaceholders = printPlaceholders;
        }

        @Override
        public void write(Sentence value) throws IOException {
            writer.writeLine(value.toString(printTags, printPlaceholders));
        }

        @Override
        public void close() throws IOException {
            writer.close();
        }
    }

    private static class TokensOutputter implements Outputter {

        private final TokensOutputStream stream;

        public TokensOutputter(boolean printTags, boolean printPlaceholders) {
            stream = new TokensOutputStream(System.out, printTags, printPlaceholders);
        }

        @Override
        public void write(Sentence value) throws IOException {
            stream.write(value);
        }

        @Override
        public void close() throws IOException {
            stream.close();
        }
    }

}

@@ -247,24 +247,81 @@
 gException;%0A
+import eu.modernmt.processing.splitter.SentenceSplitter;%0A
 import org.a
@@ -1227,16 +1227,133 @@
 build();
+%0A            Option sentenceSplit = Option.builder().longOpt(%22sentence-split%22).hasArg(false).required(false).build();
 %0A%0A      
@@ -1665,24 +1665,73 @@
 eepSpaces);%0A
+            cliOptions.addOption(sentenceSplit);%0A
         %7D%0A%0A 
@@ -1942,16 +1942,52 @@
 n batch;
+%0A        public final boolean split;
 %0A%0A      
@@ -2596,24 +2596,77 @@
 n(%22batch%22);%0A
+            split = cli.hasOption(%22sentence-split%22);%0A
         %7D%0A%0A 
@@ -3307,32 +3307,44 @@
 e, input, output
+, args.split
 );%0A            e
@@ -3423,24 +3423,36 @@
 nput, output
+, args.split
 );%0A        %7D
@@ -3696,32 +3696,47 @@
 Outputter output
+, boolean split
 ) throws IOExcep
@@ -3918,37 +3918,38 @@
         
-output.write(
+write(output, 
 sentence
 );%0A     
@@ -3932,32 +3932,39 @@
 output, sentence
+, split
 );%0A        %7D%0A   
@@ -4096,16 +4096,31 @@
 r output
+, boolean split
 ) throws
@@ -4460,29 +4460,534 @@
     
-output.write(sentence
+write(output, sentence, split);%0A        %7D%0A    %7D%0A%0A    private static void write(Outputter outputter, Sentence sentence, boolean split) throws IOException %7B%0A        Sentence%5B%5D sentences = null;%0A%0A        if (split) %7B%0A            SentenceSplitter splitter = new SentenceSplitter(sentence);%0A            sentences = splitter.split();%0A        %7D%0A%0A        if (sentences == null) %7B%0A            outputter.write(sentence);%0A        %7D else %7B%0A            for (Sentence sentenceSplit : sentences)%0A                outputter.write(sentenceSplit
 );%0A 

Update to PreprocessorMain: new option '--sentence-split' is now available