/**
 * i-net software provides programming examples for illustration only, without warranty
 * either expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and/or fitness for a particular purpose. This programming example
 * assumes that you are familiar with the programming language being demonstrated and
 * the tools used to create and debug procedures. i-net software support professionals
 * can help explain the functionality of a particular procedure, but they will not modify
 * these examples to provide added functionality or construct procedures to meet your
 * specific needs.
 *
 * Copyright © 1999-2025 i-net software GmbH, Berlin, Germany.
**/
package designer;

import java.awt.Component;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;

import com.inet.designer.AbstractDesignerDataModel;
import com.inet.designer.EmbeddedUtils;
import com.inet.designer.Startup;
import com.inet.report.Area;
import com.inet.report.DefaultValue;
import com.inet.report.Engine;
import com.inet.report.Field;
import com.inet.report.FormulaField;
import com.inet.report.Paragraph;
import com.inet.report.PromptField;
import com.inet.report.RDC;
import com.inet.report.Region;
import com.inet.report.ReportException;
import com.inet.report.Section;
import com.inet.report.Text;
import com.inet.report.TextPart;

/**
 * This sample shows how to use the DesignerDataModel classes. Instead of using real files this model uses a very simple
 * virtual file system which is represented by a {@link java.util.Map}.
 */
public class DesignerModel {

    static final Object[] VIRTUAL_FILENAMES  = { "Default", "MyReport-1", "MyReport-2" };

    static final Map      VIRTUAL_FILESYSTEM = new HashMap();

    private static int    promptFieldCounter = 0;

    /**
     * Load an engine from virtual file system.
     * @param selectedValue chosen engine from virtual file system
     * @return created engine
     * @throws ReportException if there are problems loading a new engine
     * @throws IOException if there are IO issues
     */
    static private Engine load( Object selectedValue ) throws ReportException, IOException {
        final byte[] rpt = (byte[])VIRTUAL_FILESYSTEM.get( selectedValue );
        return rpt == null ? null : RDC.loadEngine( null, new ByteArrayInputStream( rpt ), null, null );
    }

    /**
     * Save an engine to virtual file system.
     * @param selectedValue chosen engine from virtual file system
     * @param e engine to save into the virtual file system
     * @throws ReportException if there are problems during the save of the engine
     * @throws IOException if there are problems writing to the stream
     */
    static private void save( Object selectedValue, Engine e ) throws ReportException, IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        RDC.saveEngine( out, e );
        VIRTUAL_FILESYSTEM.put( selectedValue, out.toByteArray() );
    }

    /**
     * Start an embedded i-net Designer.
     * @param args arguments are ignored.
     */
    public static void main( String[] args ) {
        Startup.setModel( new AbstractDesignerDataModel() {

            /**
             * when a new report is created load the default engine from our virtual file system or create a new report
             * if this is not successful.
             */
            @Override
            public Engine createNewReport( Component parent ) throws IOException, ReportException {
                Engine engine = load( "Default" );
                if( engine == null ) {
                    // no engine, create one
                    engine = RDC.createEmptyEngine( Engine.NO_EXPORT );
                    // now modify it (you could put your logo here)
                    engine.getArea( 2 ).addSection();
                    engine.getArea( 2 ).addSection();
                    engine.getArea( 2 ).addSection();
                    new Thread( new Runnable() { //openVisualDatabaseWizardDialog() must be ran in a separate Thread  
                                    @Override
                                    public void run() {
                                        //wait until the report is opened
                                        while( EmbeddedUtils.getCurrentEngine() == null ) {
                                            try {
                                                Thread.sleep( 100 );
                                            } catch( InterruptedException e ) {
                                                e.printStackTrace();
                                            }
                                        }
                                        openVisualDatabaseWizardDialog();
                                    }
                                } ).start();
                }
                return engine;
            }

            /**
             * choose report file
             */
            public File chooseReportFile( Component parent ) throws IOException, ReportException {
                return null;
            }

            /**
             * store to VFS
             */
            @Override
            public boolean saveReport( Component parent, Engine e, boolean saveAs ) throws IOException, ReportException {
                Object selectedValue =
                    JOptionPane.showInputDialog( null, "Choose a report", "File", JOptionPane.INFORMATION_MESSAGE, null, VIRTUAL_FILENAMES,
                                                 VIRTUAL_FILENAMES[0] );
                if( selectedValue != null ) {
                    save( selectedValue, e );
                    return true;
                } else {
                    return false;
                }
            }

            @Override
            public FormulaField openUserFormulaDialog( FormulaField formulafield ) {
                if( formulafield == null ) { //If the formula is null, the user wants to create a new formula
                    try {
                        formulafield =
                            EmbeddedUtils.getCurrentEngine().getFields()
                                         .addFormulaField( "Example Formula", "//This is an Example Formula:\n1 + 1", FormulaField.FORMULA_USER );
                    } catch( ReportException e ) {
                        e.printStackTrace(); //If en error occur print the stacktrace and show the error dialog
                        showErrorDialog( e );
                    }
                }
                return super.openUserFormulaDialog( formulafield );
            }

            @Override
            public void openParameterDialog( PromptField parameterField ) {
                if( parameterField == null ) { //if parameterField is null, the user wants to create a new parameter field
                    try {
                        parameterField =
                            EmbeddedUtils.getCurrentEngine().getFields()
                                         .addPromptField( "PromptField No." + promptFieldCounter, "<Enter prompt description>", Field.STRING ); //Create a default parameter field
                        parameterField.setDefaultValues( new DefaultValue[] { new DefaultValue( "\"<Enter default value>\"", null ) } ); //Set the default value for the created field
                    } catch( Exception e ) {
                        e.printStackTrace();
                        showErrorDialog( e );
                    }
                }
                super.openParameterDialog( parameterField );
            }

            @Override
            public void addedSubreport( Engine engine ) {
                try {
                    Area area = engine.getArea( Region.DETAIL ); //Get the subreport´s detail area
                    Section sec = area.getSection( 0 ); //get the section of the area
                    sec.setHeight( 500 );
                    Text text = sec.addText( 0, 0, 2200, 500 ); //add a text element to the section
                    Paragraph p = text.addParagraph();
                    TextPart part = p.addTextPart( "Subreport!" );
                    part.setFontSize( 20 );
                    part.setBold( true );
                    part.setFontColor( RDC.COLOR_RED );
                } catch( ReportException e ) {
                    e.printStackTrace();
                    showErrorDialog( e );
                }
            }

            private void showErrorDialog( Exception e ) { //Simple example for an error dialog
                String errorText = e.getMessage(); //read error text
                StringWriter s = new StringWriter();
                e.printStackTrace( new PrintWriter( s ) ); //read stacktrace
                JTextPane message = new JTextPane(); //Create a textfield to show error message ant stacktrace
                message.setEditable( false );
                message.setText( errorText + "\n\n" + s.toString() );
                JOptionPane.showMessageDialog( EmbeddedUtils.getParentComponent(), message, errorText, JOptionPane.ERROR_MESSAGE ); //open the dialog, as parent use the designer parent frame which you can get with EmbeddedUtils.getParrentComponent() 
            }

            /**
             * Choosing a location is the task of the programmer who may use any Swing component.
             * @param parent The parent Component.
             */
            @Override
            public Engine loadReport( Component parent ) throws IOException, ReportException {
                return loadReportFrom( parent, null );
            }

            /**
             * Choosing a location is the task of the programmer who may use any Swing component.
             * @param parent The parent Component.
             * @param dir The target directory where the file chooser should open.
             */
            @Override
            public Engine loadReportFrom( Component parent, File dir ) throws IOException, ReportException {
                // get report file from file chooser.
                JFileChooser fileChooser = new JFileChooser( dir );
                int returnVal = fileChooser.showOpenDialog( parent );
                if( returnVal == JFileChooser.APPROVE_OPTION ) {
                    File selectedFile = fileChooser.getSelectedFile();
                    return RDC.loadEngine( selectedFile );
                }
                return null;
            }

        } );
        Startup.startEmbedded( new Properties() ); //Start the designer with the designerdatamodel
    }

}