package OOXMLconvert;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

/**
 *
 * @author ferou
 */
public class OOXMLrels {

	// konstanty
	private static final String ps = File.separator;
	private static final int basicRels = 1;
	private static final int mainDocRels = 2;
	private static final int numberingsRels = 3;
		
	// vztahy
	/** umiestnenie hlavneho dokumentu */
	public File mainDoc = null;
	/** umiestnenie stylov */
	public File stylesFile = null;
	/** umiestnenie cislovania */
	public File numberingFile = null;
	/** umiestnenie footnotes */
	public File footnotesFile = null;
	/** umiestnenie endnotes */
	public File endnotesFile = null;
	/** umiestnenie komentárov */
	public File commentsFile = null;
	/** umiestnenie theme */
	public File themeFile = null;
	/** umiestnenie obrázkov */
	public HashMap<String,File> imgFiles = new HashMap<String, File>();
	/** umiestnenie obrázkov číslovania */
	public HashMap<String,File> numberingsImgFiles = new HashMap<String, File>();
	/** zoznam hyperliniek */
	public HashMap<String,String> hyperlinks = new HashMap<String, String>();

	/**
	 * Konštruktor
	 */
	public OOXMLrels() {
		// noop
	}

	/**
	 * Funkcia prečíta vzťah a ak treba, tak ho uloží.
	 * @param id id atribút
	 * @param type type atribút
	 * @param target target atribút
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	private boolean addRel(int relType, String id, String type, String target, String targetMode) {
		try {
			if (relType == basicRels) {
				// ak sa jedna o zakladne vztahy
				if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")) {
					this.mainDoc = getFileFromDOCX(target);
				}
			}
			else if (relType == mainDocRels) {
				// ak sa jedna o vztahy k hlavnemu dokumentu
				if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles")) {
					this.stylesFile = getFileFromMainDoc(target);
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering")) {
					this.numberingFile = getFileFromMainDoc(target);
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes")) {
					this.footnotesFile = getFileFromMainDoc(target);
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes")) {
					this.endnotesFile = getFileFromMainDoc(target);
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments")) {
					this.commentsFile = getFileFromMainDoc(target);
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme")) {
					this.themeFile = getFileFromMainDoc(target);
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")) {
					this.imgFiles.put(id, getFileFromMainDoc(target));
				}
				else if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")) {
					if ((targetMode != null) && (targetMode.trim().equals("External"))) {
						this.hyperlinks.put(id, target);
					}
				}
			}
			else if (relType == numberingsRels) {
				if (type.trim().equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")) {
					this.numberingsImgFiles.put(id, getFileFromMainDoc(target));
				}
			}
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (addRel): " + e.toString());
			return false;
		}
	}
	
	/**
	 * Funkcia vráti k relatívnej ceste v štruktúre dokumentu súbor
	 * @param relativePath relatívna cesta k súboru
	 * @return súbor
	 */
	private File getFileFromDOCX(String relativePath) {
		try {
			String p = Global.ooxmlParams.tmpDir.getAbsolutePath();
			p = Functions.addEndSlash(p);
			File retF = new File(p + relativePath);
			return retF;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (getFileFromDOCX): " + e.toString());
			return null;
		}
	}
	
	/**
	 * Funkcia vráti k relatívnej ceste v adresári hlavného dokumentu súbor
	 * @param relativePath relatívna cesta k súboru
	 * @return súbor
	 */
	private File getFileFromMainDoc(String relativePath) {
		try {
			String p = this.mainDoc.getParent();
			if (!p.endsWith("/") && !p.endsWith("\\")) {
				p += ps;
			}
			File retF = new File(p + relativePath);
			return retF;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (getFileFromMainDoc): " + e.toString());
			return null;
		}
	}
	
	/**
	 * Funkcia prečíta základné vzťahy v dokumente.
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	private boolean readRelationships() {
		try {
			File rels = getFileFromDOCX("_rels"+ps+".rels");
			// parse XML
			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(rels);
			Element root = doc.getRootElement();
			List children = root.getChildren();
			Iterator iterator = children.iterator();
			while (iterator.hasNext()) {
				Element child = (Element) iterator.next();
				addRel(basicRels, child.getAttributeValue("Id"), child.getAttributeValue("Type"), child.getAttributeValue("Target"), null);
			}
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (readRelationships): " + e.toString());
			return false;
		}
	}
	
	/**
	 * Funkcia prečíta vzťahy k hlavnému dokumentu.
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	private boolean readDocumentRelationships() {
		try {
			File rels = getFileFromMainDoc("_rels"+ps+mainDoc.getName()+".rels");
			// parse XML
			if (rels.exists()) {
				SAXBuilder builder = new SAXBuilder();
				Document doc = builder.build(rels);
				Element root = doc.getRootElement();
				List children = root.getChildren();
				Iterator iterator = children.iterator();
				while (iterator.hasNext()) {
					Element child = (Element) iterator.next();
					addRel(mainDocRels, child.getAttributeValue("Id"), child.getAttributeValue("Type"), child.getAttributeValue("Target"), child.getAttributeValue("TargetMode"));
				}
			}
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (readDocumentRelationships): " + e.toString());
			return false;
		}
	}
	
	/**
	 * Funkcia prečíta vzťahy k numberings.
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	private boolean readNumberingsRelationships() {
		try {
			File rels = getFileFromMainDoc("_rels"+ps+numberingFile.getName()+".rels");
			// parse XML
			if (rels.exists()) {
				SAXBuilder builder = new SAXBuilder();
				Document doc = builder.build(rels);
				Element root = doc.getRootElement();
				List children = root.getChildren();
				Iterator iterator = children.iterator();
				while (iterator.hasNext()) {
					Element child = (Element) iterator.next();
					addRel(numberingsRels, child.getAttributeValue("Id"), child.getAttributeValue("Type"), child.getAttributeValue("Target"), child.getAttributeValue("TargetMode"));
				}
			}
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (readNumberingsRelationships): " + e.toString());
			return false;
		}
	}
	
	/**
	 * Funkcia prečíta všetky potrebné vzťahy
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	public boolean readRels() {
		try {
			// precitame a nastav vztahy
			if (!readRelationships()) {
				return false;
			}

			// precitame vztahy k hlavnemu dokumentu
			if (!readDocumentRelationships()) {
				return false;
			}
			
			// precitame vztahy k numberings
			if (this.numberingFile != null) {
				if (!readNumberingsRelationships()) {
					return false;
				}
			}
			
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (readRels): " + e.toString());
			return false;
		}
	}
	
}
