package dfatool.io;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import dfatool.strategy.elements.NamedElement;


public abstract class ElementIOXML<T extends NamedElement> {
	
	protected Map<String, T> map;
	protected String filename;
	
	public ElementIOXML(String filename) {
		this.filename = filename;
		map = readFromFile();
	}
	
	public Map<String, T> mapElements() {
		if(map == null) return readFromFile();
		return map;
	}
	
	public void setElements(Map<String, T> map){
		this.map = map;
	}
	
	public Collection<T> listElements() {
		return map.values();
	}

	public T getElement(String name) {
		return map.get(name);
	}
	
	public void updateElement(T t) {
		map.put(t.getName(), t);
		writeToFile();
	}
	public void removeElement(T t) {
		map.remove(t.getName());
		writeToFile();
	}
	
	public void writeToFile() {
		XMLOutputFactory oFactory = XMLOutputFactory.newInstance();
		FileWriter fw = null;
		XMLStreamWriter writer = null;
		try {
			fw = new FileWriter(filename);
			writer = oFactory.createXMLStreamWriter(fw);
			writer.writeStartDocument();
			writer.writeStartElement("root");
			writeElements(writer);
			writer.writeEndElement();
			writer.writeEndDocument();
			writer.flush();
			writer.close();
			fw.flush();
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (XMLStreamException e) {
			e.printStackTrace();
		}finally{
			try {
				writer.close();
			} catch (XMLStreamException e) {
				e.printStackTrace();
			}
			
			try {
				fw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	protected abstract void writeElements(XMLStreamWriter writer) throws XMLStreamException;
	
	public Map<String,T> readFromFile(){
	Map<String, T> map = new HashMap<String, T>();
	FileReader fr = null;
	XMLStreamReader reader = null;
	try {
		XMLInputFactory iFactory = XMLInputFactory.newInstance();
		fr = new FileReader(filename);
		reader = iFactory.createXMLStreamReader(fr);
		map = readElements(reader);
		reader.close();
		fr.close();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (XMLStreamException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	return map;	
	}

	protected abstract Map<String, T> readElements(XMLStreamReader reader) throws XMLStreamException ;

	public boolean skipToNextStartElement(XMLStreamReader reader) throws XMLStreamException{
		if(reader.hasNext()) reader.next();
		while (reader.hasNext() && !reader.isStartElement()) reader.next(); 
		return reader.hasNext();
	}
	
	public String readText(XMLStreamReader reader) throws XMLStreamException{
		String ret = "";
		while(reader.hasNext() && !reader.isCharacters()) reader.next();
		while(reader.hasNext() && reader.isCharacters()){ 
			ret += reader.getText();
			reader.next();
		}
		return ret;
	}

}
