package OOXMLconvert;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;
import org.jdom.Element;

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

	// konstanty
	private static final int BUFFER = 2048;
	
	/**
	 * Funkcia vytvorí unikátny dočasný adresár
	 * @return dočasný adresár
	 * @throws java.io.IOException
	 */
    public static File createTempDirectory() throws java.io.IOException {
		String pathPrefix = System.getProperty("java.io.tmpdir");
		if (!pathPrefix.endsWith("/") && !pathPrefix.endsWith("\\")) {
			pathPrefix += File.separator;
		}
        java.util.Random random = new java.util.Random();
		for (int maxAttempts = 100; maxAttempts > 0; --maxAttempts) {
            String path = pathPrefix + "ooxmlctmp" + File.separator + Math.abs(random.nextLong());
            java.io.File tmpDir = new java.io.File(path);
            if (tmpDir.exists()) {
                continue;
            } else {
                tmpDir.mkdir();
                return tmpDir;
            }
        }
        throw new java.io.IOException("Can't create temporary directory.");
    }

	/**
	 * Funkcia odzipuje obsah súboru.
	 * @param inFile vstupný (zazipovaný) súbor
	 * @param outFolder výstupný adresár
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	public static boolean unZip(File inFile, File outFolder) {
		try {
			if (!inFile.exists()) {
				System.err.println("Nepodarilo sa nájsť súbor " + inFile.getName() + "!");
				return false;
			}
			if (!outFolder.isDirectory()) {
				outFolder.mkdirs();
			}
			BufferedOutputStream out = null;
			ZipInputStream in = new ZipInputStream(new BufferedInputStream(new FileInputStream(inFile)));
			ZipEntry entry;
			while((entry = in.getNextEntry()) != null) {
				
				int count;
				byte data[] = new byte[BUFFER];
				
				String p = outFolder.getPath() + File.separator + entry.getName();
				p = p.replace('/', File.separatorChar);
				p = p.replace('\\', File.separatorChar);
				//System.out.println(p);
				File f = new File(p);
				f.getParentFile().mkdirs();
				// ak je entry subor, tak ho zapis
				if (!entry.isDirectory()) {
					out = new BufferedOutputStream(new FileOutputStream(p), BUFFER);

					while ((count = in.read(data,0,BUFFER)) != -1) {
						out.write(data,0,count);
					}
					out.flush();
					out.close();
				}
			}
			in.close();
			return true;
		}
		catch (Exception e) {
			System.err.println("Functions -> unZip: " + e.toString());
			return false;
		}
	}
	
	/**
	 * Funkcia zmaže adresár vrátane jeho obsahu
	 * @param path cesta k adresár
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	public static boolean deleteDir(File path) {
		try {
			if(path.exists()) {
				File[] files = path.listFiles();
				for(int i = 0; i < files.length; i++) {
					if(files[i].isDirectory()) {
						deleteDir(files[i]);
					}
					else {
						files[i].delete();
					}
				}
			}
			return (path.delete());
		}
		catch (Exception e) {
			System.err.println("Functions -> getExtensideleteDiron: " + e.toString());
			return false;
		}
	}

	/**
	 * Funkcia konvertuje Object na integer.
	 * @param o Object na skonvertovanie
	 * @param defaultValue default hodnota
	 * @return číselná hodnota objektu
	 */
	public static int intValDef(Object o, int defaultValue) {
		try {
			return Integer.parseInt(o.toString());
		}
		catch (Exception e) {
			// noop
		}
		return defaultValue;
	}

	/**
	 * Funkcia zistí príponu súboru.
	 * @param f súbor
	 * @return príponu ako String
	 */
	public static String getExtension(File f) {
		try {
			String filename = f.getName();
			String ext = (filename.lastIndexOf(".") == -1) ? "" : filename.substring(filename.lastIndexOf(".") + 1, filename.length());
			return ext;
		}
		catch (Exception e) {
			System.err.println("Functions -> getExtension: " + e.toString());
			return "";
		}
	}
	
	/**
	 * Funkcia konvertuje EMU jednotky používané v DrawingML na pixely.
	 * @param emu hodnota EMU
	 * @return vracia hodnotu v pixeloch
	 */
	public static int emuToPx(int emu) {
		try {
			int px = emu / 9525;
			return px;
		}
		catch (Exception e) {
			System.err.println("Functions -> getPxFromEMU: " + e.toString());
			return 0;
		}
	}
	
	/**
	 * Funkcia konvertuje EMU jednotky používané v DrawingML na centimetre.
	 * @param emu hodnota EMU
	 * @return vracia hodnotu v centimetroch
	 */
	public static int emuToCm(int emu) {
		try {
			int px = emu / 360000;
			return px;
		}
		catch (Exception e) {
			System.err.println("Functions -> getPxFromEMU: " + e.toString());
			return 0;
		}
	}
	
	/**
	 * Funkcia pridá k ceste súboru na koniec file separator (/,\)
	 * @param s String obsahujúci path
	 * @return String obsahujúci path na konci s file separatorom
	 */
	public static String addEndSlash(String s) {
		try {
			String retS = s;
			if (!retS.endsWith("/") && !retS.endsWith("\\")) {
				retS += File.separator;
			}			
			return retS;
		}
		catch (Exception e) {
			System.err.println("Functions -> addEndSlash: " + e.toString());
			return "";
		}
	}
	
	/**
	 * Funkcia zmení všetky lomítka v ceste na webovské lomítka
	 * @param s String obsahujúci path
	 * @return String obsahujúci path
	 */
	public static String setWebSlashes(String s) {
		try {
			String retS = s;
			retS = retS.replace('\\', '/');
			return retS;
		}
		catch (Exception e) {
			System.err.println("Functions -> addEndSlash: " + e.toString());
			return "";
		}
	}
	
	/**
	 * Funkcia skopíruje súbor do zvoleného súboru
	 * @param fromFile kopírovaný súbor
	 * @param toFile kam sa má súbor skopírovať
	 * @throws java.io.IOException
	 */
	public static void copyFile(File fromFile, File toFile) throws IOException {
		FileInputStream from = null;
		FileOutputStream to = null;
		try {
			from = new FileInputStream(fromFile);
			to = new FileOutputStream(toFile);
			byte[] buffer = new byte[4096];
			int bytesRead;
			
			while ((bytesRead = from.read(buffer)) != -1) {
				to.write(buffer, 0, bytesRead); // write
			}
		} 
		finally {
			if (from != null) {
				try {
					from.close();
				} 
				catch (IOException e) {
					// noop
				}
			}
			if (to != null) {
				try {
					to.close();
				} 
				catch (IOException e) {
					// noop
				}
			}
		}
	}
	
	/**
	 * Funkcia k danej ceste vráti relatívnu cestu k root
	 * @param path cesta k súboru, pre ktorý chceme zistiť relatívnu cestu
	 * @return relatívnu cestu k root
	 */
	public static String getRelativePathToRoot(String path) {
		try {
			String retPath = "";
			String[] p = path.split("/");
			int count = p.length - 1; // -1 -> pretoze na konci je subor
			for (int i = 0; i < count; i++) {
				retPath += "../";
			}
			return retPath;
		}
		catch (Exception e) {
			System.err.println("Functions -> getRelativePathToRoot: " + e.toString());
			return "";
		}
	}
	
	/**
	 * Funkcia prejde daným elementom a vráti všetok zobraziteľný text.
	 * @param el element, ktorý chceme prezrieť
	 * @return String textový obsah
	 */
	public static String getTextFromElement(Element el) {
		try {
			String retText = "";
			String elText = el.getText();
			if ((elText != null) && (!elText.trim().isEmpty())) {
				retText += elText;
			}
			List elChildren = el.getChildren();
			Iterator i = elChildren.iterator();
			while (i.hasNext()) {
				Element elChild = (Element) i.next();
				retText += " " + getTextFromElement(elChild).trim();
			}
			return retText.trim();
		}
		catch (Exception e) {
			System.err.println("Functions -> getTextFromElement: " + e.toString());
			return "";
		}
	}
	
	/**
	 * Funkcia zistí, či sa hodnoty v1 a v2 približne rovnajú s toleranciou +/- t
	 * @param v1 prvá hodnota na porovnanie
	 * @param v2 druhá hodnota na porovnanie
	 * @param t tolerancia
	 * @return <i>true</i> ak sa hodnoty rovnajú s danou toleranciou, <i>false</i> inak
	 */
	public static boolean almostEquals(int v1, int v2, int t) {
		try {
			if (v1 > v2) {
				int pom = v1;
				v1 = v2;
				v2 = pom;
			}
			// vo v1 je mensie z nich
			if ((v1 + t) >= v2) {
				return true;
			}
			return false;
		}
		catch (Exception e) {
			System.err.println("Functions -> almostEquals: " + e.toString());
			return false;
		}
	}
}
