/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2007 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  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 3 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 PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.io.XMLio;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;  
import org.xml.sax.SAXParseException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;


import com.approximatrix.draco.analysis.ui.AnalysisChildDialog;
import com.approximatrix.draco.application.ChildFrameRegistrar;
//import com.approximatrix.draco.application.ChildDialog;
import com.approximatrix.draco.fit.ui.FitChildDialog;

public class AnalysisDatabase {
	
	private static final int REGRESSION_ANALYSIS = 0;
	private static final int SIMPLE_ANALYSIS = 1;

	private ChildFrameRegistrar master = null;
	private Document result = null;
	
	private NodeList analyses = null;
	
	public AnalysisDatabase(ChildFrameRegistrar parent) {
		master = parent;
	}
	
	public AnalysisDatabase() {
		// Just a dummy
	}
	
	public Document getDOMrepresentation() {
    	
    	if(result != null) return result;
    	
        result = null;
        try {
            DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            result = dbuild.newDocument();
            Element collection = result.createElement(AnalysisTags.ANALYSIS_MASTER_TAG);
            Element body = result.createElement(AnalysisTags.ANALYSIS_BODY_TAG);
            
            // First the regression dialogs
            Object[] fits = master.getWindowsByClass(FitChildDialog.class);
            if(fits != null) {
            	for(int i=0;i<fits.length;i++) {
                	if(!((FitChildDialog)fits[i]).getAnalysis().isSuccessful())
                		continue;
                	AnalysisIO.SaveFitAnalysis(body,(FitChildDialog)fits[i]); 
            	}
            }
            
			// Now the pure analyses
            Object[] analyses = master.getWindowsByClass(AnalysisChildDialog.class);
            if(analyses != null) {
            	for(int i=0;i<analyses.length;i++) {
            		if(!((AnalysisChildDialog)analyses[i]).getAnalysis().isSuccessful())
                		continue;
                	AnalysisIO.SaveSimpleAnalysis(body,(AnalysisChildDialog)analyses[i]); 
                	break;
            	}
            }
                        
            collection.appendChild(body);
            result.appendChild(collection);
            
        } catch (Exception e) {
            System.out.println("Exception caught..." + e);
            e.printStackTrace();
        }
        return result;
	}
	
	/** Returns the number of analyses currently loaded into memory
	 * 
	 * @return integer representing the number of analyses loaded or stored
	 */
	public int getAnalysisCount() {
		if(analyses == null) {
			if(!loadAnalyses()) return 0;
		}
		return analyses.getLength();
	}
	
	/** Returns a requested analysis from the loaded list
	 * 
	 * @param index the index of the requested analysis
	 * @return an Element representing the analysis structure, or null if a problem occurred
	 */
	public Element getAnalysis(int index) {
		if(analyses == null) {
			if(!loadAnalyses()) return null;
		}
		if(index < 0 || index >= getAnalysisCount()) return null;
		return (Element)analyses.item(index);
	}
	
	/** Private function that extracts a NodeList of analysis elements from the
	 * DOM master.
	 * 
	 * @return true if successfully loaded, false otherwise
	 */
	private boolean loadAnalyses() {
		Element everything = result.getDocumentElement();
		//Element everything = result.getElementById(AnalysisTags.ANALYSIS_MASTER_TAG);
		if(everything == null) return false;
		
		NodeList bodies = everything.getElementsByTagName(AnalysisTags.ANALYSIS_BODY_TAG);

		if(bodies == null) return false;
		if(bodies.getLength() != 1) return false;
		Element body = (Element)bodies.item(0);

		// Get the analyses
		analyses = body.getElementsByTagName(AnalysisTags.ANALYSIS_ELEMENT);
		return (analyses != null);
	}
	
	public boolean loadDOMrepresentation(InputStream in) {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			result = builder.parse(in);
		} catch (SAXParseException spe) {
			return false;
		} catch (SAXException sxe) {
			// Error generated during parsing
			Exception  x = sxe;
			if (sxe.getException() != null)
				x = sxe.getException();
			x.printStackTrace();
			return false;
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
			return false;
		} catch (IOException ioe) {
			ioe.printStackTrace();
			return false;
	    }
		return true;
	}
}
