/*
 * Packer.java
 *
 */
package com.uvigo.tMaestro.SCOCreator.tool.packer;

import com.uvigo.tMaestro.SCOCreator.tool.MainFrame;
import com.uvigo.tMaestro.SCOCreator.tool.Capsula;
import com.uvigo.tMaestro.SCOCreator.tool.MyOptionPane;
import com.uvigo.tMaestro.SCOCreator.tool.properties.Propiedad;
import com.uvigo.tMaestro.SCOCreator.tool.ProgressBar;

/**
 * Esta clase es la encargada de empaquetar todos los elementos necesarios
 * en un jar para que asi, el Jar constituya un SCO que se ejecute
 * sin problemas en el destino.
 * @author raul
 */
public class Packer {

    /**
     * Relacion de dependencias de una clase.
     */
    private java.util.HashMap<String, java.util.ArrayList<String>> oDependences;
    /**
     * Referencia al directorio en el que copiar el SCO si operamos en modo
     * arbol de directorios.
     */
    private java.io.File oOutputDir;
    /**
     * Referencia al Jar del SCO si operamos en modo Jar
     */
    private java.util.jar.JarOutputStream oOutputJar;
    /**
     * Channel asociado al Jar
     */
    private java.nio.channels.WritableByteChannel oJarChannel;
   
    /**
     * Crea una nueva instancia de esta clase. Obtiene las relaciones de dependencias
     * conocidas por la aplicacion. estas se encuentran guardadas en ficheros .xml.
     * Las lee de los ficheros .xml y las alamcena en la estructura oDependences
     */
    public Packer() {
    //M: ahora vacio
    }

    /**
     * En modo jar: Esta funcion crea el SCO (fichero jar con todos los recursos necesarios) en el lugar indicado por oFile.
     * Coloca en el, ademas de la clase de la plantilla: todas las clases que necesitan los elementos componentes
     * de la plantilla (dependencias consultadas en el fichero de dependencias), ficheros asociados a propiedades (por ej: una imagen), etc
     * En modo arbol de directorios hace lo mismo pero guarda todo en el directorio denotado por oFile
     * @param oFile La ruta en donde guadar el .jar (SCO), o el directorio en el que guardar todo
     * @param oBar Referencia a la barra de progreso que puede estar lanzada en el entorno. Null si no la hay
     * @throws java.lang.Exception Si se produce algun error durante la generaci�n del fichero .jar
     */
    public void pack(java.io.File oFile, ProgressBar oBar) throws Exception {
        if (oBar != null) {
            System.out.println("Creando SCO");
            oBar.setLabelText(MainFrame.oMainFrame.getMessage("Label11"));
            oBar.addValue();
        }
        oOutputDir = null;
        oOutputJar = null;
        oJarChannel = null;

        try {
            //Creamos el OutputStream
                oOutputDir = oFile;

            if (oBar != null) {
                 System.out.println("Añadiendo recursos");
                oBar.setLabelText(MainFrame.oMainFrame.getMessage("Label14"));
                oBar.addValue();
            }
            //Anadimos los ficheros correspondientes a aquellas propiedades que, referidas a ficheros,
            //han sido mofificadas respecto a los valores de la plantilla original.
            //Estos ficheros se encyentran en el directorio components del proyecto actual. Por tanto anadimos
            //el directorio Componets (si existe, claro).

            java.io.File oDirComponents = new java.io.File(MainFrame.oMainFrame.fTemp,"/COMPONENTS"); //-M- 
            addEntry(oDirComponents,"COMPONENTS");

            if (oBar != null) {
                 System.out.println("A�adiendo ficheros de opciones, adaptaci�n y plantilla");
                oBar.setLabelText(MainFrame.oMainFrame.getMessage("Label15"));
                oBar.addValue();
            }

            //Amadimos los ficheros .xml de opciones. M: desde TEMP
            java.io.File oDirOptions = new java.io.File(MainFrame.oMainFrame.fTemp, "/OPTIONS");
            addEntry(oDirOptions, "OPTIONS");

            //Anadimos el fichero .xml de adaptacion. M: desde TEMP
            java.io.File oDirAdaptation = new java.io.File(MainFrame.oMainFrame.fTemp, "/ADAPTATION");
            addEntry(oDirAdaptation, "ADAPTATION");


            //M: Anadimos nuestra plantilla
            java.io.File fCurrentTemplate = new java.io.File(MainFrame.oMainFrame.fTemplates,"/"+MainFrame.oMainFrame.getTemplateName());
            addEntry(fCurrentTemplate,"TEMPLATE");

            if (oBar != null) {
                 System.out.println("Cerrando el fichero y finalizando el proceso");
                oBar.setLabelText(MainFrame.oMainFrame.getMessage("Label16"));
                oBar.addValue();
            }
             System.out.println("fin de pack");
        } catch (Exception oE) { //Si se produce algun error eliminamos el fichero .jar o el directorio
            oE.printStackTrace();
            if (oFile.isFile()) oFile.delete();
            else { //Eliminamos los contenidos del directorio
                MainFrame.deleteDir(oFile);
            }
            throw new Exception(MainFrame.oMainFrame.getMessage("Error22"));
        }
    }

    /**
     * Si trabajamos en modo Jar: Esta funcion anade al fichero jar denotado por oOutputJar, el fichero denotado por oFileEntry. Lo a�ade con el
     * nombre de sEntryName. Si oFileEntry es un directorio anade todos sus ficheros. Es una funcion
     * recursiva con lo que los directorios pueden anidarse.
     * En modo arbol de directorios copia oFileEntry al directorio oOutputDir
     * @param oFileEntry El fichero o directorio que se desea anadir al jar o al arbol de directorios segun el modo
     * @param sEntryName El nombre con el que se va a anadir la entrada.
     * @throws java.io.IOException Si se produce algun error al tratar de anadir el fichero al jar
     */
    private void addEntry(java.io.File oFileEntry, String sEntryName) throws java.io.IOException {
        java.io.File[] oFiles;
     
            if (oFileEntry.isDirectory()) {
                java.io.File oDir = new java.io.File(oOutputDir, sEntryName);
                if (!oDir.exists()) oDir.mkdir();
                oFiles = oFileEntry.listFiles();
            } else {
                oFiles = new java.io.File[1];
                oFiles[0] = oFileEntry;
            }
            for (int i = 0; i < oFiles.length; i++) {
                if (oFiles[i].isDirectory()) {
                    addEntry(oFiles[i], sEntryName + "/" + oFiles[i].getName());
                    continue;
                }
                //Vemos si el directorio al que va destinado el fichero ya esta creado
                //Si no lo esta lo creamos
                java.io.File oDirFile = new java.io.File(oOutputDir, sEntryName);
                if (!oDirFile.exists()) oDirFile.mkdirs();
                java.io.File oOutputFile = new java.io.File(oDirFile, oFiles[i].getName());
                MainFrame.copyFile(oFiles[i], oOutputFile);
            }
      
    }

 
}
