/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOUSE. See the GNU
 * General Public License for more details.
 *
 * You should have recieved a copy of the GNU General Public License
 * along with this program; if not write to the Free Software
 * Foundation, inc., 59 Temple Place, Suite 330, Boston MA 02111-1307
 * USA
 */

package run;

/**
 * Insert the type's description here. Creation date: (2001-08-20 21:59:33)
 */
import java.util.*;
import java.io.*;

import run.readers.FembicReader;
import run.readers.GmshReader;
import run.readers.NastranReader;
import run.writers.FembicWriter;

import uka.karmi.rmi.RemoteException;


public class Translator {
    private int number_of_elements;
    private int number_of_trackers;
    private int number_of_nodes;
    private int number_of_materials;
    private int number_of_controls;
    private RplVector nodelist;
    private Hashtable nodetable;
    private RplVector elementlist;
    private RplVector trackerlist;
    private RplVector materiallist;
    private double time;
    private int i;
    private RplVector constraintlist;
    private RplVector loadlist;
    private int number_of_constraints;
    private int number_of_loads;
    private Controlset controlset;
    private Element temporary_element;
    private Tracker temporary_tracker;
    private Constraint temporary_constraint;
    private Node temporary_node;
    private Writer resultwriter;
    private java.lang.String filename;
    private double timestep;
    private boolean failure_is_set = false;

    /**
     * ModelSmp constructor comment.
     */
    public Translator() {
        super();
    }

    /**
     * This method does nothing in the translator. Creation date: (2001-08-20
     * 22:03:32)
     */
    public void assembleMassMatrix()
        throws IllegalArgumentException
    {
        int i;
        Node temp_node;
        Element temp_element;
        Constraint temp_constraint;

        try {
            System.out.println("Assembling Constraints");

            for (i = 0; i < number_of_constraints; i++) {
                temp_constraint = (Constraint) constraintlist.elementAt(i);
                temp_constraint.determineMassMatrix(nodelist);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException(
                "\n* Error during Assembly phase - Terminating" + e
            );
        } catch (NullPointerException e) {
            throw new IllegalArgumentException(
                "\n* Error during Assembly phase of Constraint \n* This error could be the result of a missing (or wrong) parameter in the indata file \n* " +
                e
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(
                "\n* Error during Assembly phase of Constraint \n* This error could be the result of a missing (or wrong) parameter in the indata file \n* " +
                e
            );
        }
    }

    /**
     * This method initializes the problem in the following steps: 1. Create a
     * file object so that the indata file can be read. 2. Question the file
     * object of all the variables etc that is required to set up all the
     * memory variables etc correctly. 3. Set up the variables 4. Finished
     * Creation date: (2001-08-20 22:01:54)
     *
     * @param filename java.lang.String
     */
    public void initialize(String infile, String outfile)
        throws IllegalArgumentException, RemoteException
    {

	Reader indatafile;
	double frac, frac2;

		if (infile.trim().toUpperCase().endsWith(".NAS") || infile.trim().toUpperCase().endsWith(".NASTRAN"))
	        // Create an indata file object that we can ask for the things we require
    	    indatafile = new NastranReader(infile.trim());

		else 

		if (infile.trim().toUpperCase().endsWith(".MSH"))
	        // Create an indata file object that we can ask for the things we require
    	    indatafile = new GmshReader(infile.trim());

		else 


		if (infile.trim().toUpperCase().endsWith(".IN"))
	        // Create an indata file object that we can ask for the things we require
    	    indatafile = new FembicReader(infile.trim());

		else		

		throw new IllegalArgumentException("Error: Unrecognized infile. .nas or .nastran is currently supported \n");

        try {

			indatafile.preProcess();

        } catch (java.text.ParseException e) {
            // If we end up here, something is wrong in the indata file
            throw new IllegalArgumentException("Error during file preprocessing \n" + e);
        }


        // Set number of elements, materials and nodes
        try {
            number_of_elements = indatafile.numberOfElements();
            number_of_trackers = indatafile.numberOfTrackers();
            number_of_materials = indatafile.numberOfMaterials();
            number_of_nodes = indatafile.numberOfNodes();
            number_of_constraints = indatafile.numberOfConstraints();
            number_of_loads = indatafile.numberOfLoads();
            number_of_controls = indatafile.numberOfControls();
        } catch (java.text.ParseException e) {
            // If we end up here, something is wrong in the indata file
            throw new IllegalArgumentException("Error in initialization phase \n" + e);
        }

        //Set up the arrays to handle the entries
        elementlist = new RplVector(number_of_elements);
        trackerlist = new RplVector(number_of_trackers);
        materiallist = new RplVector(number_of_materials);
        nodelist = new RplVector(number_of_nodes);
        nodetable = new Hashtable(number_of_nodes);
        constraintlist = new RplVector(number_of_constraints);
        loadlist = new RplVector(number_of_loads);
        controlset = new Controlset();

        try {

            //Fill the nodelist array
            indatafile.open();
            System.out.println("Reading Nodes");
			frac2 = 0;

			for (i = 0; i < number_of_nodes; i++) {
			    
			    temporary_node = indatafile.getNextNode(constraintlist, loadlist);
			    
			    nodelist.addElement(temporary_node);
			    nodetable.put(new Integer(temporary_node.getNumber()), temporary_node);
			    
			    frac = i*10 / number_of_nodes;
			    frac %= 10;
			    
			    if (frac != frac2) {
			        System.out.println("" + 10*frac + "% complete");
			        frac2 = frac;
			    }

            }

            indatafile.close();
            System.out.println("Filled nodelist");

            //Fill the constraintlist array
            System.out.println("Reading Constraints");
            indatafile.open();

			frac2 = 0;

            for (i = 0; i < number_of_constraints; i++) {
                constraintlist.addElement(
                    indatafile.getNextConstraint(nodelist)
                );

			frac = i*10 / number_of_constraints;
			frac %= 10;

			if (frac != frac2) {
				System.out.println("" + 10*frac + "% complete");
				frac2 = frac;
			}
                
            }

            indatafile.close();
            System.out.println("Filled constraintlist");


            //Fill the loadlist array
            System.out.println("Reading Loads");
            indatafile.open();

			frac2 = 0;

            for (i = 0; i < number_of_loads; i++) {
                loadlist.addElement(indatafile.getNextLoad(nodelist));

			frac = i*10 / number_of_loads;
			frac %= 10;

			if (frac != frac2) {
				System.out.println("" + 10*frac + "% complete");
				frac2 = frac;
			}
            }

            indatafile.close();
            System.out.println("Filled loadlist");


            //Fill the materials array
            indatafile.open();
            System.out.println("Reading Materials");
			frac2 = 0;

            Material m;

            for (i = 0; i < number_of_materials; i++) {
                m = indatafile.getNextMaterial();

                if (m.failure_strain_is_set || m.failure_stress_is_set) {
                    failure_is_set = true;
                }

                materiallist.addElement(m);

				frac = i*10 / number_of_materials;
				frac %= 10;

				if (frac != frac2) {
					System.out.println("" + 10*frac + "% complete");
					frac2 = frac;
				}

            }

            indatafile.close();
            System.out.println("Filled materiallist");

            //Fill the Elements array
            indatafile.open();
            System.out.println("Reading Elements");

			frac2 = 0;

            for (i = 0; i < number_of_elements; i++) {

                elementlist.addElement(
                    indatafile.getNextElement(materiallist, nodelist, loadlist, nodetable)
                );

			frac = i*10 / number_of_elements;
			frac %= 10;

			if (frac != frac2) {
				System.out.println("" + 10*frac + "% complete");
				frac2 = frac;
			}
		

            }

            indatafile.close();
            System.out.println("Filled elementlist");


            //Get the controlset
            indatafile.open();
            System.out.println("Reading Controls");

            for (i = 0; i < number_of_controls; i++) {
                indatafile.getControlSet(controlset);
            }

            indatafile.close();
            System.out.println("Filled controlset");

            // Create an outdata file that will print the results in the format we wish. This is a special method for translator only
            resultwriter = new FembicWriter(nodelist, elementlist, controlset, constraintlist, materiallist, loadlist
                );

        } catch (java.text.ParseException e) {
            // If we end up here, something is wrong in the indata file, reading the parameters
            throw new IllegalArgumentException(
                "Parameter error in indata file \n" + e + " in line " +
                e.getErrorOffset()
            );
        } catch (IllegalArgumentException e) {
            throw e;
        }

        //Initialize the writer
        try {
            resultwriter.initialize();
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Initialization error of writer");
        }

		// Set up the filename for translated file
		filename = outfile.trim();

    }


    /**
     * Cross connect pass_1
     * 22:03:07)
     */
    public void setInitialConditions() {
        int i;
        int j;
        Node temp_node;
        Element temp_element;
        Constraint temp_constraint;

        // Cross connect pass_1
        System.out.println("Initializing nodes");

        for (i = 0; i < number_of_nodes; i++) {
            temp_node = (Node) nodelist.elementAt(i);
            temp_node.setInitialConditions();
        }

        // Initialize all the elements
        System.out.println("Initializing elements");

        for (i = 0; i < number_of_elements; i++) {
            temp_element = (Element) elementlist.elementAt(i);
            temp_element.setInitialConditions();
        }

        // Initialize all the constraints
        System.out.println("Initializing constraints");

        for (i = 0; i < number_of_constraints; i++) {
            temp_constraint = (Constraint) constraintlist.elementAt(i);
            temp_constraint.setInitialConditions();
        }

        // Initialize the controlset
        controlset.setInitialConditions();

    }

    /**
     * Cross connect pass_2
     * Creation date: (2001-08-20 22:03:47)
     */
    public void solve() {

    }


    /**
     * Write the translated file. Creation date: (2001-08-20
     * 22:03:57)
     */
    public void post() {

		try {    	
        resultwriter.write(filename, time);
        } catch (IOException ioe) {
            System.out.println(ioe);
            return;
        }

    	
    }



}

