package OOXMLconvert;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedHashMap;

/**
 *
 * @author ferou
 */
public class OOXMLparams {
	
	// konstanty - default hodnoty
	/** default hodnota relativnej cesty k adresaru, kde sa ulozia obrazky */
	private final String imgDirDef = "pics/";
	/** nazov CSS suboru */
	private final String cssFileName = "styles.css";
	/** default hodnota relativnej cesty k adresaru, kde sa ulozia CSS */
	private final String cssDirDef = "styles/" + cssFileName;
	/** default hodnota urovne zachovania formatovania */
	private final int formatPreservingLevelDef = 1;
	/** default hodnota ci sa maju prenasat obrazky */
	private final boolean preserveImagesDef = true;
	/** default hodnota kvality jpeg kompresie pouzitej na obrazkoch */
	private final float jpegQualityDef = 0.8f;
	/** default hodnota ci sa pouzije heuristika na rozoznavanie nadpisov */
	private final boolean useHHeuristicDef = true;
	/** default nazov stylu pre nadpis úrovne 1 */
	private final String heading1StyleNameDef = "heading1";
	/** default nazov stylu pre nadpis úrovne 2 */
	private final String heading2StyleNameDef = "heading2";
	/** default nazov stylu pre nadpis úrovne 3 */
	private final String heading3StyleNameDef = "heading3";
	/** default HTML tag pre nadpis */
	private final String htmlTagForHeadingDef = "h1";
	/** default hodnota ci sa maju prenasat footnotes */
	private final boolean preserveFootnotesDef = false;
	/** default hodnota ci sa maju prenasat endnotes */
	private final boolean preserveEndnotesDef = false;
	/** default hodnota typ prepojenia na CSS */
	private final int cssConnectionTypeDef = 0;
	/** default hodnota CSS trieda pre bold */
	private final String cssBDef = "bold";
	/** default hodnota CSS trieda pre italic */
	private final String cssIDef = "italic";
	/** default hodnota CSS trieda pre underline */
	private final String cssUDef = "underline";
	/** default hodnota CSS trieda pre strike */
	private final String cssSDef = "strike";
	/** default hodnota CSS trieda pre superscript */
	private final String cssUIDef = "super";
	/** default hodnota CSS trieda pre subscript */
	private final String cssLIDef = "sub";
	
	// parametre
	/** input súbor (DOCX súbor na skonvertovanie) */
	public File docxSource = null;
	/** output súbor (HTML súbor do ktorého sa uloží výstup) */
	public File xhtmlDest = null;
	/** relativna cesta k adresaru, kde sa ulozia obrazky */
	public String imgDir = imgDirDef;
	/** relativna cesta k adresaru, kde sa ulozia CSS */
	public String cssDir = cssDirDef;
	/** uroven zachovania formatovania (od 0 do 2) */
	public int formatPreservingLevel = formatPreservingLevelDef;
	/** urcuje, ci sa maju prenasat obrazky */
	public boolean preserveImages = preserveImagesDef;
	/** kvalita jpeg kompresie pouzitej na obrazkoch */
	public float jpegQuality = jpegQualityDef;
	/** urcuje, ci sa pouzije heuristika na rozoznavanie nadpisov */
	public boolean useHHeuristic = useHHeuristicDef;
	/** nazov stylu pre nadpis úrovne 1 */
	public String heading1StyleName = heading1StyleNameDef;
	/** nazov stylu pre nadpis úrovne 2 */
	public String heading2StyleName = heading2StyleNameDef;
	/** nazov stylu pre nadpis úrovne 3 */
	public String heading3StyleName = heading3StyleNameDef;
	/** HTML tag pre nadpis */
	public String htmlTagForHeading = htmlTagForHeadingDef;
	/** urcuje, ci sa maju prenasat footnotes */
	public boolean preserveFootnotes = preserveFootnotesDef;
	/** urcuje, ci sa maju prenasat endnotes */
	public boolean preserveEndnotes = preserveEndnotesDef;
	/** typ prepojenia na CSS */
	public int cssConnectionType = cssConnectionTypeDef;
	/** CSS input subor */
	public File cssSource = null;
	/** CSS trieda pre bold */
	public String cssB = cssBDef;
	/** CSS trieda pre italic */
	public String cssI = cssIDef;
	/** CSS trieda pre underline */
	public String cssU = cssUDef;
	/** CSS trieda pre strike */
	public String cssS = cssSDef;
	/** CSS trieda pre superscript */
	public String cssUI = cssUIDef;
	/** CSS trieda pre subscript */
	public String cssLI = cssLIDef;
	
	// zaloha parametrov
	/** parameter určuje, či už bol vykonaný backup */
	private boolean isBackup = false;
	/** záloha input súbor (DOCX súbor na skonvertovanie) */
	private File _docxSource = null;
	/** záloha output súbor (HTML súbor do ktorého sa uloží výstup) */
	private File _xhtmlDest = null;
	/** záloha relativna cesta k adresaru, kde sa ulozia obrazky */
	private String _imgDir = "";
	/** záloha relativna cesta k adresaru, kde sa ulozia CSS */
	private String _cssDir = "";
	/** záloha uroven zachovania formatovania (od 0 do 2) */
	private int _formatPreservingLevel = formatPreservingLevelDef;
	/** záloha urcuje, ci sa maju prenasat obrazky */
	private boolean _preserveImages = preserveImagesDef;
	/** záloha kvalita jpeg kompresie pouzitej na obrazkoch */
	private float _jpegQuality = jpegQualityDef;
	/** záloha urcuje, ci sa pouzije heuristika na rozoznavanie nadpisov */
	private boolean _useHHeuristic = useHHeuristicDef;
	/** záloha nazov stylu pre nadpis úrovne 1 */
	private String _heading1StyleName = "";
	/** záloha nazov stylu pre nadpis úrovne 2 */
	private String _heading2StyleName = "";
	/** záloha nazov stylu pre nadpis úrovne 3 */
	private String _heading3StyleName = "";
	/** záloha HTML tag pre nadpis */
	private String _htmlTagForHeading = "";
	/** záloha urcuje, ci sa maju prenasat footnotes */
	private boolean _preserveFootnotes = preserveFootnotesDef;
	/** záloha urcuje, ci sa maju prenasat endnotes */
	private boolean _preserveEndnotes = preserveEndnotesDef;
	/** záloha typ prepojenia na CSS */
	public int _cssConnectionType = cssConnectionTypeDef;
	/** záloha CSS input subor */
	public File _cssSource = null;
	/** záloha CSS trieda pre bold */
	public String _cssB = cssBDef;
	/** záloha CSS trieda pre italic */
	public String _cssI = cssIDef;
	/** záloha CSS trieda pre underline */
	public String _cssU = cssUDef;
	/** záloha CSS trieda pre strike */
	public String _cssS = cssSDef;
	/** záloha CSS trieda pre superscript */
	public String _cssUI = cssUIDef;
	/** záloha CSS trieda pre subscript */
	public String _cssLI = cssLIDef;
	
	/** docasny pracovny adresar */
	public File tmpDir = null;

	/**
	 * Konštruktor
	 */
	public OOXMLparams() {
		// noop
	}
	
	/**
	 * Funkcia zazálohuje všetky premenné.
	 */
	public void backup() {
		try {
			if (!isBackup) {
				isBackup = true;
				_docxSource = docxSource;
				_xhtmlDest = xhtmlDest;
				_imgDir = imgDir;
				_cssDir = cssDir;
				_formatPreservingLevel = formatPreservingLevel;
				_preserveImages = preserveImages;
				_jpegQuality = jpegQuality;
				_useHHeuristic = useHHeuristic;
				_heading1StyleName = heading1StyleName;
				_heading2StyleName = heading2StyleName;
				_heading3StyleName = heading3StyleName;
				_htmlTagForHeading = htmlTagForHeading;
				_preserveFootnotes = preserveFootnotes;
				_preserveEndnotes = preserveEndnotes;
				_cssConnectionType = cssConnectionType;
				_cssSource = cssSource;
				_cssB = cssB;
				_cssI = cssI;
				_cssU = cssU;
				_cssS = cssS;
				_cssUI = cssUI;
				_cssLI = cssLI;
			}
			else {
				throw new Exception("Backup is already done.");
			}
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (backup): " + e.toString());
		}
	}

	/**
	 * Funkcia obnoví všetky premenné.
	 */
	public void restore() {
		try {
			if (isBackup) {
				docxSource = _docxSource;
				xhtmlDest = _xhtmlDest;
				imgDir = _imgDir;
				cssDir = _cssDir;
				formatPreservingLevel = _formatPreservingLevel;
				preserveImages = _preserveImages;
				jpegQuality = _jpegQuality;
				useHHeuristic = _useHHeuristic;
				heading1StyleName = _heading1StyleName;
				heading2StyleName = _heading2StyleName;
				heading3StyleName = _heading3StyleName;
				htmlTagForHeading = _htmlTagForHeading;
				preserveFootnotes = _preserveFootnotes;
				preserveEndnotes = _preserveEndnotes;
				cssConnectionType = _cssConnectionType;
				cssSource = _cssSource;
				cssB = _cssB;
				cssI = _cssI;
				cssU = _cssU;
				cssS = _cssS;
				cssUI = _cssUI;
				cssLI = _cssLI;
				isBackup = false;
			}
			else {
				throw new Exception("No previous backup has been made.");
			}
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + " (restore): " + e.toString());
		}
	}

	private boolean setParam(String key, String value) {
		try {
			if (key.equals("i")) {
				// input súbor (DOCX súbor na skonvertovanie)
				this.docxSource = new File(value);
			}
			else if (key.equals("o")) {
				// output súbor (HTML súbor do ktorého sa uloží výstup)
				this.xhtmlDest = new File(value);
			}
			else if (key.equals("co")) {
				// relativna cesta k suboru, kde sa ulozia CSS
				this.cssDir = Functions.addEndSlash(value) + cssFileName;
			}
			else if (key.equals("io")) {
				// relativna cesta k adresaru, kde sa ulozia obrazky
				this.imgDir = Functions.addEndSlash(value);
			}
			else if (key.equals("fl")) {
				// uroven zachovania formatovania (od 0 do 2)
				this.formatPreservingLevel = Functions.intValDef(value, formatPreservingLevelDef);
			}
			else if (key.equals("pi")) {
				// urcuje, ci sa maju prenasat obrazky (y/n)
				if (value.trim().equals("n")) {
					this.preserveImages = false;
				}
				else {
					this.preserveImages = true;
				}
			}
			else if (key.equals("jq")) {
				// kvalita jpeg kompresie pouzitej na obrazkoch (od 1 do 100)
				int percDef = Math.round(jpegQualityDef * 100);
				int perc = Functions.intValDef(value, percDef);
				if ((perc < 1) || (perc > 100)) {
					perc = percDef;
				}
				this.jpegQuality = 1.0f * perc / 100;
			}
			else if (key.equals("hh")) {
				// urcuje, ci sa ma pouzit heuristika na rozoznavanie nadpisov (y/n)
				if (value.trim().equals("n")) {
					this.useHHeuristic = false;
				}
				else {
					this.useHHeuristic = true;
				}
			}
			else if (key.equals("hs1")) {
				if (!value.trim().isEmpty()) {
					this.heading1StyleName = value.trim().toLowerCase();
				}
				else {
					this.heading1StyleName = this.heading1StyleNameDef.toLowerCase();
				}
			}
			else if (key.equals("hs2")) {
				if (!value.trim().isEmpty()) {
					this.heading2StyleName = value.trim().toLowerCase();
				}
				else {
					this.heading2StyleName = this.heading2StyleNameDef.toLowerCase();
				}
			}
			else if (key.equals("hs3")) {
				if (!value.trim().isEmpty()) {
					this.heading3StyleName = value.trim().toLowerCase();
				}
				else {
					this.heading3StyleName = this.heading3StyleNameDef.toLowerCase();
				}
			}
			else if (key.equals("ht")) {
				if (!value.trim().isEmpty()) {
					this.htmlTagForHeading = value.trim();
				}
				else {
					this.htmlTagForHeading = this.htmlTagForHeadingDef;
				}
			}
			else if (key.equals("pf")) {
				// urcuje, ci sa maju preniest footnotes
				if (value.trim().equals("n")) {
					this.preserveFootnotes = false;
				}
				else {
					this.preserveFootnotes = true;
				}
			}
			else if (key.equals("pe")) {
				// urcuje, ci sa maju preniest endnotes
				if (value.trim().equals("n")) {
					this.preserveEndnotes = false;
				}
				else {
					this.preserveEndnotes = true;
				}
			}
			else if (key.equals("ct")) {
				// typ prepojenia na CSS
				this.cssConnectionType = Functions.intValDef(value,0);
			}
			else if (key.equals("ci")) {
				// CSS input subor
				this.cssSource = new File(value);
			}
			else if (key.equals("cssb")) {
				// CSS style pre bold
				this.cssB = value.trim();
			}
			else if (key.equals("cssi")) {
				// CSS style pre italic
				this.cssI = value.trim();
			}
			else if (key.equals("cssu")) {
				// CSS style pre underline
				this.cssU = value.trim();
			}
			else if (key.equals("csss")) {
				// CSS style pre strike
				this.cssS = value.trim();
			}
			else if (key.equals("cssui")) {
				// CSS style pre superscript
				this.cssUI = value.trim();
			}
			else if (key.equals("cssli")) {
				// CSS style pre subscript
				this.cssLI = value.trim();
			}
			else {
				System.err.println("Neznamy parameter - \"" + key + "\"");
				return false;
			}
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + ": " + e.toString());
			return false;
		}
	}
	
	/** 
	 * Funkcia, ktorá nastaví parametre.
	 * @param params parametre zo vstupu
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	public boolean setParams(String[] params) {
		try {
			// nastav parametre zo vstupu
			for (int i = 0; i < params.length; i = i + 2) {
				String keyS = params[i].trim();
				if (!keyS.startsWith("-")) {
					return false;
				}
				String key = keyS.substring(1).trim();
				String value = params[i+1].trim();
				if (!setParam(key, value)) {
					return false;
				}
			}

			// nastav automaticke parametre
			this.tmpDir = Functions.createTempDirectory();
			
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + ": " + e.toString());
			return false;
		}
	}
	
	/** 
	 * Funkcia, ktorá nastaví parametre.
	 * @param params parametre v LinkedHashMap
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	public boolean setParams(LinkedHashMap<String,String> params) {
		try {
			Iterator i = params.keySet().iterator();
			while (i.hasNext()) {
				String keyS = (String)i.next();
				if (!keyS.startsWith("-")) {
					return false;
				}
				String key = keyS.substring(1).trim();
				String value = params.get(keyS);
				if (!setParam(key, value)) {
					return false;
				}
			}
			
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + ": " + e.toString());
			return false;
		}
	}
	
}
