/*---------------------------------------------------------------------------*\
**$Author: saulius $
**$Date: 2018-05-09 00:33:22 +0300 (Wed, 09 May 2018) $
**$Revision: 168 $
**$URL: svn+ssh://www.crystallography.net/home/coder/svn-repositories/smiles-scripts/tags/v0.2.0/src/cdkdepict.java $
\*---------------------------------------------------------------------------*/

// This CLI Java program reads SMILES strings, optionally supplemented
// with IDs, and depicts these in a (nice) graphical
// representation. Output is in SVG format.

import org.openscience.cdk.smiles.*;
import org.openscience.cdk.silent.*;
import org.openscience.cdk.exception.*;
import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.depict.*;
import java.io.*;
import java.util.List;

class AutoKekuliseOption extends Option {

    AutoKekuliseOption( String short_name, String long_name,
                        OptionValue opt_value )
    {
        super( short_name, long_name, OptionType.OT_FUNCTION, opt_value );
    }

    int proc( String args[], int i ) {
        this.value.i = cdkdepict.KEKULISE_AUTO;
        return i;
    }
}

class KekuliseOption extends Option {

    KekuliseOption( String short_name, String long_name,
                    OptionValue opt_value )
    {
        super( short_name, long_name, OptionType.OT_FUNCTION, opt_value );
    }

    int proc( String args[], int i ) {
        this.value.i = cdkdepict.KEKULISE_TRUE;
        return i;
    }
}

class NoKekuliseOption extends Option {

    NoKekuliseOption( String short_name, String long_name,
                      OptionValue opt_value )
    {
        super( short_name, long_name, OptionType.OT_FUNCTION, opt_value );
    }

    int proc( String args[], int i ) {
        this.value.i = cdkdepict.KEKULISE_FALSE;
        return i;
    }
}

class cdkdepict {

    public static final int KEKULISE_AUTO = 0;
    public static final int KEKULISE_TRUE = 1;
    public static final int KEKULISE_FALSE = 2;
    
    static OptionValue smilesOption = new OptionValue();
    static OptionValue kekuliseOption = new OptionValue();
    static OptionValue outputFormatOption = new OptionValue("SVG");
    static OptionValue supportedFormatsOption = new OptionValue();

    static Option options[] = {
            new AutoKekuliseOption ( "-a", "--auto-kekulise",   kekuliseOption ),
            new KekuliseOption     ( "-k", "--kekulise",        kekuliseOption ),
            new NoKekuliseOption   ( "-k-","--no-kekulise",     kekuliseOption ),
            new NoKekuliseOption   ( null, "--dont-kekulise",   kekuliseOption ),
            new NoKekuliseOption   ( null, "--do-not-kekulise", kekuliseOption ),

            new SVGOutputOption    ( "-S", "--svg-output", outputFormatOption ),
            new EPSOutputOption    ( "-E", "--eps-output", outputFormatOption ),
            new PDFOutputOption    ( "-P", "--pdf-output", outputFormatOption ),

            new Option ( null, "--supported-formats", OptionType.OT_BOOLEAN_TRUE,
                         supportedFormatsOption ),

            new Option          ( "-s", "--smiles",  OptionType.OT_STRING, smilesOption ),
            new VersionOption   ( null, "--version", OptionType.OT_FUNCTION ),
            new CDKDepictHelp   ( null, "--help",    OptionType.OT_FUNCTION ),
        };
    
    private static final String progName = CDKDepictHelp.progName;

    public static void main( String[] argv ) throws CDKException, IOException
    {
        String filenames[] = null;
        try {
            filenames = SOptions.get_options( argv, options );
        }
        catch (SOptionsException e) {
            System.err.println( progName + ": " + e.getMessage() );
            System.exit(1);
        }

        DepictionGenerator dg = new DepictionGenerator();
        SmilesParser sp =
            new SmilesParser(SilentChemObjectBuilder.getInstance());

        if( smilesOption.present ) {
            try {
                String out = depictString4smiles(smilesOption.s, sp, dg,
                                                 kekuliseOption,
                                                 outputFormatOption,
                                                 supportedFormatsOption);
                if( out != null ) {
                    System.out.print(out);
                }
                System.exit(0);
            }
            catch(Exception e) {
                System.err.println( progName + ": " + e);
                System.exit(1);
            }
        }
        
        if( filenames == null || filenames.length == 0 ) {
            filenames = new String[] { "-" };
        }
        for( String filename : filenames ) {
            try {
                InputStreamReader reader;
                if( filename.equals("-") ) {
                    reader = new InputStreamReader( System.in );
                } else {
                    reader = new FileReader(filename);
                }
                BufferedReader br = new BufferedReader( reader );

                int count = 1;
                String line;
                while( (line = br.readLine()) != null ) {
                    String parts[] = line.trim().split("[ \t]+");
                    if( parts != null &&
                        (parts.length == 1 || parts.length == 2)) {
                        String smiles = parts[0];
                        String ident = parts.length > 1 ? parts[1] : null;
                        try {
                            String out = depictString4smiles(smiles, sp, dg,
                                                             kekuliseOption,
                                                             outputFormatOption,
                                                             supportedFormatsOption);
                            if( out != null ) {
                                System.out.print(out);
                            }
                        }
                        catch(Exception e) {
                            System.err.println( progName + ": " + filename +
                                                "(" + count + ")" +
                                                (ident != null? " " + ident : "") +
                                                ": ERROR, " + e);
                        }
                    } else {
                        int maxlen = 20;
                        System.err.println
                            ( progName + ": " + filename + "(" + count + "): " +
                              "WARNING, could not get SMILES and " +
                              "identifier from string '" +
                              line.substring(0,line.length() < maxlen ?
                                             line.length() : maxlen ) +
                              (line.length() < maxlen ? "" : "...") +
                              "'" );
                    }
                    count++;
                } // while
            } // try
            catch(Exception e) {
                System.err.println( progName + ": " + "WARNING, " + e );
            }
        } // for
    }

    private static String depictString4smiles( String smiles, SmilesParser sp,
                                               DepictionGenerator dg,
                                               OptionValue kekuliseOption,
                                               OptionValue outputFormatOption,
                                               OptionValue supportedFormatsOption)
        throws InvalidSmilesException, CDKException, IOException
    {
        IAtomContainer ac;
        if( kekuliseOption.i == KEKULISE_AUTO ) {
            sp.kekulise(true);
            try {
                ac = sp.parseSmiles(smiles);
            }
            catch (InvalidSmilesException ex) {
                sp.kekulise(false);
                ac = sp.parseSmiles(smiles);
            }
        } else {
            if( kekuliseOption.i == KEKULISE_TRUE ) {
                sp.kekulise(true);
            } else {
                sp.kekulise(false);
            }
            ac = sp.parseSmiles(smiles);
        }
        if( supportedFormatsOption.bool == true ) {
            Depiction d = dg.depict(ac); 
            List<String> formats = d.listFormats();
            String result = "";
            String separator = "";
            for( String format : formats ) {
                result += separator + format;
                separator = " ";
            }
            return result + "\n";
        } else {
            if( outputFormatOption.s.equals("SVG")) {
                return dg.depict(ac).toSvgStr();
            } else if( outputFormatOption.s.equals("EPS")) {
                return dg.depict(ac).toEpsStr();
            } else if( outputFormatOption.s.equals("PDF")) {
                return dg.depict(ac).toPdfStr();
            } else {
                assert false : "Format '" + outputFormatOption.s + "' " +
                    "is not supported";
                return null;
            }
        }
    }
    
} // class cdkdepict
