package com.bitrazor.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import com.bitrazor.jaxb.regionmaster.Region;
import com.bitrazor.jaxb.regionmaster.RegionDescriptionFileURLs;
import com.bitrazor.jaxb.regionmaster.Regions;

/**
 * This class:
 * - provides the main API for interacting with the RegionMaster file
 * - makes use of the JAXB-generated classes
 * - uses the RegionIdentifier class to hold the names and IDs 
 * - provides a constructor for use via URL
 * - provides a constructor for use via local file
 * 
 * @author David Staas, bitrazor.com
 *
 */
public class RegionMaster {
	public static final String jaxbPackage = "com.bitrazor.jaxb.regionmaster";

	private URL masterURL = null;
	private String masterFilename = null;
	private Regions regions = null;
	private JAXBContext jaxbContext = null;
	private Unmarshaller unmarshaller = null;

	public RegionMaster(URL masterURL) {
		setMasterURL(masterURL);
		setMasterFilename(null);
		setJaxbContext(RegionMaster.setContext(jaxbPackage));
		unmarshaller = RegionMaster.getUnmarshaller(jaxbContext);
		try {
			regions = (Regions) unmarshaller.unmarshal(masterURL);
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	public RegionMaster(String masterFilename) {
		setMasterFilename(masterFilename);
		setMasterURL(null);
		JAXBContext jc = RegionMaster.setContext(jaxbPackage);
		unmarshaller = RegionMaster.getUnmarshaller(jc);
		try {
			regions = (Regions) unmarshaller.unmarshal(new FileInputStream(
					"RegionMaster.xml"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JAXBException e) {
			e.printStackTrace();
		}

	}

	public void dump() {
		List regionList = regions.getRegion();
		// For each region
		for (Iterator iter = regionList.iterator(); iter.hasNext();) {
			dump((Region) iter.next());
		}
	}

	public String getMasterFilename() {
		return masterFilename;
	}

	public void setMasterFilename(String filename) {
		this.masterFilename = filename;
	}

	public URL getMasterURL() {
		return masterURL;
	}

	public void setMasterURL(URL masterURL) {
		this.masterURL = masterURL;
	}

	public static JAXBContext setContext(String jaxbPackage) {
		JAXBContext jc = null;
		try {

			// Set the JAXB context to the package name we uses
			// when we created all the JAXB classes from the XSD
			jc = JAXBContext.newInstance(jaxbPackage);
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		return jc;
	}

	public static Unmarshaller getUnmarshaller(JAXBContext jc) {
		Unmarshaller u = null;

		try {
			// Create an unmarshaller (unmarshal from XML to Java objects)
			u = jc.createUnmarshaller();
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		return u;
	}

	public static Regions getRegions(URL masterURL, Unmarshaller u) {
		Regions regions = null;

		return regions;
	}

	// Display contents for a region to the console. This should be called
	// for each region in the RegionMaster file.
	public static void dump(Region region) {
		System.out.println("Region found:");
		System.out.println("  ID: " + region.getRegionID() + ", Name: "
				+ region.getRegionName());

		RegionDescriptionFileURLs rdfurls = (RegionDescriptionFileURLs) region
				.getRegionDescriptionFileURLs();
		List rdfUrlList = rdfurls.getRegionDescriptionFileURL();

		// Print out each RDF URL
		for (Iterator rdfurl = rdfUrlList.iterator(); rdfurl.hasNext();) {
			System.out.println("  URL: " + rdfurl.next());
		}

	}

	/**
	 * Gets all of the regions out of the Region Master file, extracts their
	 * name and ID, and sticks these two values into a RegionIdentifier object.
	 * Creates an ArrayList of these and returns that list in the order
	 * they're listed in the file.  If you want them sorted by name, you can do:
	 * 
	 * 		ArrayList al = rm.getRegionIdentifiers();
	 * 		Collections.sort(al, new RegionIdentifierCompareByName());
	 * 		for (Iterator iter = al.iterator(); iter.hasNext();) {
	 * 			RegionIdentifier rid = (RegionIdentifier)iter.next();
	 * 			rid.dump(); // or whatever else you want 
	 * 		}
	 * @return
	 *     An ArrayList of RegionIdentifiers (names and IDs).
	 */
    ArrayList getRegionIdentifiers() {
		ArrayList al = new ArrayList();
		Region currentRegion;
		List regionList = regions.getRegion();
		// For each region
		for (Iterator iter = regionList.iterator(); iter.hasNext();) {
			currentRegion = (Region) iter.next();
			String currentID = String.valueOf(currentRegion.getRegionID());
			RegionIdentifier rid = new RegionIdentifier(
					currentRegion.getRegionName(), currentID);
			al.add(rid);
		}
		return(al);
    }

	/**
	 * Given an ID, returns an ArrayList of Strings that represent URLs that point
	 * to the region description file for that region.  Note that the RegionMaster
	 * should not have more than one entry for a region ID; if for some reason it
	 * does, the first one listed in the file is operated on.
	 * 
	 * @param id
	 *     The ID of the region to look for.
	 * @return
	 *     An ArrayList of Strings (URLs), or null if ID not found.
	 */
	ArrayList getURLsByID(int id) {
		ArrayList al = new ArrayList();
		List regionList = regions.getRegion();
		
		// For each region
		for (Iterator iter = regionList.iterator(); iter.hasNext();) {
			Region region = (Region)iter.next();
			if (region.getRegionID() == id) {
				// Found a match, return the URLs as an ArrayList
				
				// Get the container
				RegionDescriptionFileURLs rdfurls = (RegionDescriptionFileURLs) region
				.getRegionDescriptionFileURLs();
				
				// Get the first one inside for the iterator
		        List rdfUrlList = rdfurls.getRegionDescriptionFileURL();
				
				// Iterate through them, add them to the ArrayList
			 	for (Iterator rdfurl = rdfUrlList.iterator(); rdfurl.hasNext();) {
					String s = (String)rdfurl.next();
					al.add(s);
					//System.out.println("  URL: " + rdfurl.next());
				}
				return(al);
			}
		}
		// If we fell through here, ID was not found; return null
		return(null);

	}

	public JAXBContext getJaxbContext() {
		return jaxbContext;
	}

	public void setJaxbContext(JAXBContext jc) {
		this.jaxbContext = jc;
	}

	public Unmarshaller getUnmarshaller() {
		return unmarshaller;
	}

	public void setU(Unmarshaller unmarshaller) {
		this.unmarshaller = unmarshaller;
	}

}

