package com.github.tkurz.sesame.vocab;

import org.apache.commons.cli.*;
import org.apache.commons.lang3.StringUtils;
import org.openrdf.model.util.GraphUtilException;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFParseException;
import org.openrdf.rio.Rio;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * ...
 * <p/>
 * @author  Thomas Kurz (tkurz@apache.org)
 * @author  Jakob Frank (jakob@apache.org)
 */
public class Main {

    public static void main(String [] args) {
        try {
            CommandLineParser parser = new PosixParser();
            CommandLine cli = parser.parse(getCliOpts(), args);

            if (cli.hasOption('h')) {
                printHelp();
                return;
            }

            // two args must be left over: <input-inputFile> <output-inputFile>
            String[] cliArgs = cli.getArgs();
            final String input, output;
            switch (cliArgs.length) {
                case 0:
                    throw new ParseException("Missing input-file");
                case 1:
                    input = cliArgs[0];
                    output = null;
                    break;
                case 2:
                    input = cliArgs[0];
                    output = cliArgs[1];
                    break;
                default:
                    throw new ParseException("too many arguments");
            }

            RDFFormat format = Rio.getParserFormatForMIMEType(cli.getOptionValue('f', null));
            final VocabBuilder builder = new VocabBuilder(input, format);

            if (cli.hasOption('p')) {
                builder.setPackageName(cli.getOptionValue('p'));
            }
            if (cli.hasOption('n')) {
                builder.setName(cli.getOptionValue('n'));
            }
            if (cli.hasOption('u')) {
                builder.setPrefix(cli.getOptionValue('u'));
            }
            if (cli.hasOption('s')) {
                try {
                    builder.setIndent(StringUtils.repeat(' ', Integer.parseInt(cli.getOptionValue('s', "4"))));
                } catch (NumberFormatException e) {
                    throw new ParseException("indent must be numeric");
                }
            } else {
                builder.setIndent("\t");
            }

            if (output != null) {
                System.out.printf("Starting generation%n");
                Path outFile = Paths.get(output);
                builder.generate(outFile);
                System.out.printf("Generation finished, result available in '%s'%n", output);
            } else {
                builder.generate(System.out);
            }

        } catch (ParseException e) {
            printHelp(e.getMessage());
        } catch (RDFParseException e) {
            System.err.println("Could not parse input file: " + e.getMessage());
        } catch (FileNotFoundException e) {
            System.err.println("Could not read input-file: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("Error during file-access: " + e.getMessage());
        } catch (GraphUtilException e) {
            e.printStackTrace();
        } catch (GenerationException e) {
            System.err.printf(e.getMessage());
        }
    }

    private static void printHelp() {
        printHelp(null);
    }

    private static void printHelp(String error) {
        HelpFormatter hf = new HelpFormatter();
        PrintWriter w = new PrintWriter(System.out);
        if (error != null) {
            hf.printWrapped(w, 80, error);
            w.println();
        }
        hf.printWrapped(w, 80, "usage: Main [options...] <input-file> [<output-file>]");
        hf.printWrapped(w, 80, "  <input-file>                the input file to read from");
        hf.printWrapped(w, 80, "  [<output-file>]             the output file to write, StdOut if omitted");
        hf.printOptions(w, 80, getCliOpts(), 2, 2);
        w.flush();
        w.close();
    }

    @SuppressWarnings("AccessStaticViaInstance")
    private static Options getCliOpts() {
        Options o = new Options();

        o.addOption(OptionBuilder
                .withLongOpt("format")
                .withDescription("mime-type of the input file (will try to guess if absent)")
                .hasArgs(1)
                .withArgName("input-format")
                .isRequired(false)
                .create('f'));

        o.addOption(OptionBuilder
                .withLongOpt("package")
                .withDescription("package declaration (will use default (empty) package if absent")
                .hasArgs(1)
                .withArgName("package")
                .isRequired(false)
                .create('p'));

        o.addOption(OptionBuilder
                .withLongOpt("name")
                .withDescription("the name of the namespace (will try to guess from the input file if absent)")
                .hasArgs(1)
                .withArgName("ns")
                .isRequired(false)
                .create('n'));

        o.addOption(OptionBuilder
                .withLongOpt("uri")
                .withDescription("the prefix for the vocabulary (if not available in the input file)")
                .hasArgs(1)
                .withArgName("prefix")
                .isRequired(false)
                .create('u'));

        o.addOption(OptionBuilder
                .withArgName("spaces")
                .hasOptionalArgs(1)
                .withArgName("indent")
                .withDescription("use spaces for for indentation (tabs if missing, 4 spaces if no number given)")
                .isRequired(false)
                .create('s'));

        o.addOption(OptionBuilder
                .withLongOpt("help")
                .withDescription("pint this help")
                .isRequired(false)
                .hasArg(false)
                .create('h'));

        return o;
    }

}

@@ -1997,32 +1997,155 @@
 ;%0A            %7D%0A
+            if (cli.hasOption('l')) %7B%0A                builder.setPreferredLanguage(cli.getOptionValue('l'));%0A            %7D%0A
             if (
@@ -2162,24 +2162,24 @@
 ion('s')) %7B%0A
-
             
@@ -4234,16 +4234,17 @@
 arnings(
+%7B
 %22AccessS
@@ -4260,16 +4260,34 @@
 nstance%22
+, %22static-access%22%7D
 )%0A    pr
@@ -5883,32 +5883,32 @@
 Required(false)%0A
-
                 
@@ -5919,24 +5919,322 @@
 ate('s'));%0A%0A
+        o.addOption(OptionBuilder%0A                .withLongOpt(%22language%22)%0A                .withDescription(%22preferred language for vocabulary labels%22)%0A                .hasArgs(1)%0A                .withArgName(%22preferred-language%22)%0A                .isRequired(false)%0A                .create('l'));%0A%0A
         o.ad

Support preferred language in CLI fixes #10