/*
 *  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.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import com.approximatrix.draco.application.ChildFrameRegistrar;
import com.approximatrix.draco.plot.ui.PlotDialog;

public class PlotDatabase {

	private ChildFrameRegistrar master = null;
	private Document result = null;
	
	private NodeList plots = null;
	
	public PlotDatabase(ChildFrameRegistrar parent) {
		master = parent;
	}
	
	public PlotDatabase() {
		// 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(PlotTags.PLOT_MASTER_TAG);
            TableTags.GenerateNS(collection);
            Element body = result.createElement(PlotTags.PLOT_BODY_TAG);
            
            Object[] plots = master.getWindowsByClass(PlotDialog.class);
            if(plots != null) {
            	for(int i=0;i<plots.length;i++) {
            		PlotIO.SavePlot(body,(PlotDialog)plots[i]); 
            	}
            }
            
            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 getPlotCount() {
		if(plots == null) {
			if(!loadAnalyses()) return 0;
		}
		return plots.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 getPlot(int index) {
		if(plots == null) {
			if(!loadAnalyses()) return null;
		}
		if(index < 0 || index >= getPlotCount()) return null;
		return (Element)plots.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
		plots = body.getElementsByTagName(PlotTags.PLOT_ELEMENT);
		return (plots != 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;
	}
}

	

