#!/usr/bin/env --split-string=${JDK_HOME}/bin/java @Makeshift/java_arguments @Makeshift/java_javac_arguments

import Breccia.parser.ParseError;
import Breccia.parser.plain.BrecciaCursor;
import Breccia.XML.translator.BrecciaXCursor;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.Reader;
import Java.Unhandled;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;

import static Breccia.parser.plain.Project.newSourceReader;
import static java.lang.System.err;
import static javax.xml.transform.OutputKeys.*;


/** A shell command that runs the Breccia to X-Breccia translator on the standard in and output streams.
  *
  *     @see <a href='http://reluk.ca/project/Breccia/XML/translator/notes.brec.xht#-,input,translation'>
  *       Usage instructions</a>
  */
public final class TranslateCommand { // [AFN]


    private TranslateCommand() {}



    public static void main( final String[] _arguments ) throws IOException, XMLStreamException {
        new TranslateCommand().execute(); }



////  P r i v a t e  ////////////////////////////////////////////////////////////////////////////////////


    private void execute() throws IOException, XMLStreamException {
        try( final Reader reader = new BufferedReader( new InputStreamReader( System.in ));
             final BrecciaXCursor sourceXCursor = new BrecciaXCursor() ) {
            final BrecciaCursor sourceCursor = new BrecciaCursor();
            sourceCursor.source( reader );
            sourceXCursor.source( sourceCursor );
            try { identityTransformer.transform( new StAXSource(sourceXCursor), toOut ); } // [SNR]
            catch( final TransformerException xT ) {
                if( xT.getCause() instanceof XMLStreamException ) {
                    final XMLStreamException xS = (XMLStreamException)(xT.getCause());
                    throw (ParseError)(xS.getCause()); } /* So advertising that the location data
                      of `ParseError` is available for the exception, in case the caller wants it. */
                throw new Unhandled( xT ); }}
        catch( final ParseError x ) {
            err.print( "<input>" );
            err.print( ':' );
            err.print( x.lineNumber );
            err.print( ": " );
            err.println( x ); }}



    private final Transformer identityTransformer; {
        Transformer t;
        try { t = TransformerFactory.newInstance().newTransformer(); }
        catch( TransformerConfigurationException x ) { throw new Unhandled( x ); }
        t.setOutputProperty( ENCODING, "UTF-8" );
        t.setOutputProperty( METHOD, "XML" );
        t.setOutputProperty( OMIT_XML_DECLARATION, "yes" );
        identityTransformer = t; }



    private final StreamResult toOut = new StreamResult( System.out); }



// NOTES
// ─────
//   AFN  Atypical file naming is allowed here.  ‘The compiler does not enforce the optional restriction
//        defined at the end of JLS §7.6, that a type in a named package should exist in a file whose
//        name is composed from the type name followed by the .java extension.’
//        <https://openjdk.org/jeps/330>
//        <https://docs.oracle.com/javase/specs/jls/se11/html/jls-7.html#jls-7.6>
//
//        No longer, however, does this allowance extend to the package name.  While in JDK releases
//        prior to 22 “the launcher's source-file mode was permissive about which package, if any,
//        was declared”, current releases enforce a correspondence between the declared package name
//        and the file path.  Failing this, the launcher aborts with “end of path to source file
//        does not match its package name”.  <https://openjdk.org/jeps/458>
//
//   SNR  `StAXSource` is ‘not reusable’ according to its API.  This is puzzling, however,
//        given that it’s a pure wrapper.