// CurryModule.java

package code.modules;

import code.symbols.PrintAsTxtLoadable;
import code.symbols.Symbol;

import java.io.StringWriter;
import java.io.Writer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;

/**
 * This class stores all the information of a module, including module name,
 * imported module names, binary code and so on. All the information in this
 * class would be used as runtime module object, it has the same info as the
 * compiled module file. <P>
 * <p/>
 * <B>Class Responsibilities</B> :
 * <OL>
 * <LI> Initializes all the components of this object.</LI>
 * <LI> Print the content of this object.</LI>
 * </OL>
 * <B>Class Collaborators</B> :
 * <OL>
 * <LI> Symbol </LI>
 * </OL>
 *
 * @author jimeng
 * @since September 27, 2002
 */
public class CurryModule {

    /**
     * Name of the module which is also module file name
     */
    public final String moduleName;
    /**
     * Complete path of this module file
     */
    public final String fileLocation;
    /**
     * Store all the imported module names
     */
    private final Vector imported;
    /**
     * All the symbols in this module
     */
    private final Vector allSymbols;
    /**
     * A Boolean representing if the module was compiled or not.
     * Built-in modules are not compiled. A compiled program is a
     * compiled module.
     */
    public final boolean compiled;
    /**
     * Module's timestamp. This is contained in the module file.
     */
    public final int timestamp;

    /**
     * Initialize all the components of this object
     *
     * @param moduleName   The module's name.
     * @param imported     A vector of all the imported module names. new Vector() for internal modules.
     * @param fileLocation The complete path of this module file. null for internal modules.
     * @param timestamp     The module's timestamp as specified in the module file. 0 for internal modules.
     * @param allSymbols    A vector of allSymbols.
     * @param compiled      true if this module is a compiled module. false for internal modules.
     */

    public CurryModule(String moduleName, Vector imported, 
		       String fileLocation, int timestamp, 
		       Vector allSymbols, boolean compiled) {
        this.moduleName = moduleName;
        this.imported = imported;
        this.fileLocation = fileLocation;
        this.allSymbols = allSymbols;
        this.compiled = compiled;
        this.timestamp = timestamp;
    }

    /**
     * Gets the importedEnumeration attribute of the CurryModule object
     *
     * @return The importedEnumeration value
     */
    public Enumeration getImportedEnumeration() {
        return imported.elements();
    }


    /**
     * Gets the allSymbolsEnumeration attribute of the CurryModule object
     *
     * @return The allSymbolsEnumeration value
     */
    public Enumeration getAllSymbolsEnumeration() {
        return allSymbols.elements();
    }


    // create a format for the date and time printout
    private final static SimpleDateFormat sdf
            = new SimpleDateFormat("MM-dd-yy, HH:mm:ss");


    /**
     * Helper method for printing
     * @param out
     */
    private void println(Writer out) {
        try {
            out.write ("\n" ) ;
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
    }

    /**
     * Helper method for printing
     * @param out
     * @param str
     */
    private void println(Writer out,String str) {
        try {
            out.write (str+"\n");
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
    }

    /**
     * Prints this module in a form suitable for loading
     * as a ".txt" file.
     */
    public void printAsTxtLoadable(Writer out) {

        println(out,"COMMENT printed from loaded on " + sdf.format(new Date()));
        println(out);
        println(out,"NAME " + moduleName);
        if (compiled) {
            println(out,"COMMENT file " + fileLocation);
        }
        println(out,"COMPILED " + compiled);
        println(out,"TIME " + timestamp);
        Enumeration e = this.getImportedEnumeration();
        while (e.hasMoreElements())
            println(out,"IMPORT " + e.nextElement());
        StringWriter string = new StringWriter();
        PrintAsTxtLoadable ps = new PrintAsTxtLoadable(string);
        for (int i = 0; i < allSymbols.size(); i++)
            ((Symbol) allSymbols.elementAt(i)).accept(ps, null);
        println(out,string.toString());
    }
}

