/**
 * 
 */
package com.fitbank.bpm;

import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import com.fitbank.common.FileHelper;
import com.fitbank.common.Helper;
import com.fitbank.common.conectivity.HbSession;
import com.fitbank.common.hb.UtilHB;
import com.fitbank.common.logger.FitbankLogger;
import com.fitbank.common.properties.PropertiesHandler;
import com.fitbank.hb.persistence.trans.Tcommandmanagement;

/**
 * @author BANTEC Inc.
 */
public class Generator {
    public static void main(String[] args) {
        try {
            Helper
                    .setSession(HbSession.getInstance("com.fitbank.hb.persistence.trans.Tcommandmanagement")
                            .getSession());
            Generator gen = new Generator("CheckPayment", "Pago de Cheques", "03", "6403", "MAN");
            gen.setPrefix("fin");
            gen.generate();
            gen = new Generator("LoanSolicitude", "Solicitud de Prestamos", "06", "2000", "MAN");
            gen.setPrefix("col");
            gen.generate();
            // gen = new Generator("LoanSolicitudeAuthorization", "Autorizacion de Solicitud de Prestamos", "06",
            // "2001",
            // "MAN");
            // gen.generate();
            // gen = new Generator("AddressUpdateMaintenance", "Mantenimiento de dicecciones por Persona", "02", "3201",
            // "MAN");
            // gen.setPrefix("per");
            // gen.generate();
            // gen = new Generator("BalanceQuery", "Consulta de Saldos", "04", "4003", "CON");
            // gen.setPrefix("vis");
            // gen.generate();
        } catch (Exception e) {
            FitbankLogger.getLogger().debug(e);
        } finally {
            Helper.closeSession();
        }
    }

    private String            template;

    private String            pomTemplate;

    private String            subsystem;

    private String            transaction;

    private String            type;

    private PropertiesHandler extras;

    private String            name;

    private String            description;

    private String            prefix = "com";

    private String            path   = "/home/gfiallos/Fuentes/FIT20/fuentes/flows";

    public Generator(String pName, String pDescription, String pSubsistem, String pTransaction, String pType)
            throws Exception {
        this.name = pName;
        this.description = pDescription;
        this.subsystem = pSubsistem;
        this.transaction = pTransaction;
        this.type = pType;
        this.extras = new PropertiesHandler("extras");
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream in = classLoader.getResourceAsStream("flow.template");
        try {
            this.template = FileHelper.readStream(in);
        } finally {
            in.close();
        }
        in = classLoader.getResourceAsStream("pom.template");
        try {
            this.pomTemplate = FileHelper.readStream(in);
        } finally {
            in.close();
        }
    }

    @SuppressWarnings("unchecked")
    private List<String> findCommands() throws Exception {
        List<String> data = new ArrayList<String>();
        String hql = "from com.fitbank.hb.persistence.trans.Tcommandmanagement p where p.pk.csubsistema=:sub and "
                + "p.pk.ctransaccion=:trn and p.pk.versiontransaccion=:version and p.tipocomando=:type order by p.orden";
        UtilHB util = new UtilHB(hql);
        util.setString("sub", this.subsystem);
        util.setString("trn", this.transaction);
        util.setString("version", "01");
        util.setString("type", this.type);
        List<Tcommandmanagement> cData = util.getList();
        for (Tcommandmanagement tcommandmanagement : cData) {
            data.add(tcommandmanagement.getComando());
        }
        return data;
    }

    public void generate() throws Exception {
        String flow = this.generateFlow();
        FileHelper.writeFile(this.path + "/" + this.prefix + this.name + "/src/main/resources/" + this.name
                + ".jpdl.xml", flow);
        FileHelper.writeFile(this.path + "/" + this.prefix + this.name + "/src/main/resources/" + this.name + ".png",
                "");
        String data = MessageFormat.format(this.pomTemplate, this.prefix + this.name, this.description);
        FileHelper.writeFile(this.path + "/" + this.prefix + this.name + "/pom.xml", data);
        FitbankLogger.getLogger().debug(this.name + " ok");
    }

    private String generateFlow() throws Exception {
        List<String> commands = this.findCommands();
        List<Java> java = new ArrayList<Java>();
        String tName = "FinishTransaction";
        String tran = "toFinishTransaction";
        for (String command : commands) {
            String fname = command.substring(command.lastIndexOf('.') + 1);
            Java element = new Java(fname, command, this.extras);
            if (!java.isEmpty()) {
                Java last = java.get(java.size() - 1);
                last.addTransition(fname);
            }
            java.add(element);
        }
        if (!java.isEmpty()) {
            Java last = java.get(java.size() - 1);
            last.addTransition("FinishTransaction");
            last = java.get(0);
            tName = last.getName();
            tran = "to" + last.getName();
        }
        String javaData = "";
        int index = 0;
        for (Java java2 : java) {
            javaData += java2.formatJava(index++);
        }
        return MessageFormat.format(this.template, this.name, javaData, tran, tName, 179 + (80 * java.size()),
                179 + (80 * (java.size() + 1)));
    }

    /**
     * Entrega el Valor de path
     * 
     * @return Valor de path
     */
    public String getPath() {
        return this.path;
    }

    /**
     * Entrega el Valor de prefix
     * 
     * @return Valor de prefix
     */
    public String getPrefix() {
        return this.prefix;
    }

    /**
     * Fija el valor de la propiedad path
     * 
     * @param path
     *            El valor para path
     */
    public void setPath(String path) {
        this.path = path;
    }

    /**
     * Fija el valor de la propiedad prefix
     * 
     * @param prefix
     *            El valor para prefix
     */
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
}

class Java {
    private String            name;

    private String            javaContent;

    private List<String>      transitions = new ArrayList<String>();

    private PropertiesHandler extras;

    /**
     * Crea una nueva instancia de Generator.java
     * 
     * @param name
     * @param java
     * @param extras
     */
    public Java(String name, String java, PropertiesHandler extras) {
        super();
        this.name = name;
        this.javaContent = java;
        this.extras = extras;
    }

    public void addTransition(String pName) {
        this.transitions.add(pName);
    }

    public String formatJava(int pIndex) throws Exception {
        String template = this.extras.getStringValue("transition.template");
        String trans = "";
        for (String tr : this.transitions) {
            trans += "\n  " + MessageFormat.format(template, "to" + tr, tr);
        }
        template = this.extras.getStringValue("java.template");
        String parameter = "\n  " + this.extras.getStringValue("java.parameter");
        template = "\n"
                + MessageFormat.format(template, this.javaContent, this.name, trans + "\n", parameter,
                        179 + (pIndex * 80), 8 * this.name.length());
        return template;
    }

    /**
     * Entrega el Valor de name
     * 
     * @return Valor de name
     */
    public String getName() {
        return this.name;
    }

    /**
     * Entrega el Valor de transitions
     * 
     * @return Valor de transitions
     */
    public List<String> getTransitions() {
        return this.transitions;
    }

    /**
     * Fija el valor de la propiedad java
     * 
     * @param java
     *            El valor para java
     */
    public void setJava(String java) {
        this.javaContent = java;
    }

}
