/*
 * LangFileParser.java
 *
 * This pareses a crop_lang.xml or a operation_lang.xml file and stores information
 * into the parameter name dictionary.
 *
 * Jim Frankenberger
 * USDA-ARS, West Lafayette IN
 * jrf@purdue.edu
 *
 * Created on July 22, 2004, 3:22 PM
 *
 */
package ex1;

import de.schlichtherle.truezip.file.TFile;
import java.io.IOException;
import javax.swing.*;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;

/**
 * This pareses a crop_lang.xml or a operation_lang.xml file and stores information
 * into the parameter name dictionary. This is responsible for picking up the prompt(header),
 * choice list elements, alternate units, factor and additional adder for parameters that were defined
 * in the _DEFN file.
 *
 * @author  jrf
 */
public class LangFileParser extends DefaultHandler {

    private final DefnFileParser pNames;
    private boolean grabName, grabPrompt, grabUnit, grabFactor, grabChoice, grabAdder, grabId;
    private int choiceIndex;
    private int lastChoice;
    private final int choicesInx[];
    private final String choicesName[];
    private String name;
    private String prompt;
    private String unit;
    private String factorStr;
    private String adderStr;
    private String choiceStr;
    private float factor;
    private float adder;
    private boolean hasAltUnit, hasFactor, hasAddEnd;
    private String idStr;
    private final boolean isCropXml;

    /**
     * Creates a new instance of LangFileParser
     * @param listing
     * @param isCrop
     * @param langFile */
    public LangFileParser(DefnFileParser listing, String langFile, boolean isCrop) {
        pNames = listing;
        SAXParserFactory factory;
        SAXParser saxParser;

        isCropXml = isCrop;

        grabName = grabPrompt = grabUnit = grabFactor = grabChoice = grabAdder = grabId = false;
        hasAltUnit = hasFactor = hasAddEnd = false;
        lastChoice = 0;
        choicesInx = new int[100];
        choicesName = new String[100];

        TFile wf = new TFile(langFile);

        if (wf.exists() == false) {
            JOptionPane.showMessageDialog(null, "Error: File not found", wf.getAbsolutePath(), JOptionPane.INFORMATION_MESSAGE);

        }
        factory = SAXParserFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setXIncludeAware(true);            

        try {
            // Parse the input
            saxParser = factory.newSAXParser();
            saxParser.parse(wf, this);

        } catch (IOException | ParserConfigurationException | SAXException t) {
            t.printStackTrace();
        }
    }

    /**
     * Part of SAX XML processing... Called automatically by SAX parser
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void startDocument()
            throws SAXException {

    }

    /**
     * Part of SAX XML processing... Called automatically by SAX parser
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void endDocument()
            throws SAXException {

    }

    /**
     * Part of SAX processing that gets called at the when an opening xml tag is
     * encountered. We will filter out the ones we are interested and set the flags
     * for what the character function should grab and where it will be stored.
     * @param namespaceURI
     * @param attrs
     * @param lName local name
     * @param qName qualified name
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void startElement(String namespaceURI,
            String lName,
            String qName,
            Attributes attrs)
            throws SAXException {

        String eName = lName; // element name
        if ("".equals(eName)) {
            eName = qName;
        }
        switch (eName) {
            case "paramlang":
                hasAltUnit = hasFactor = hasAddEnd = false;
                break;
            case "paramname":
                grabName = true;
                name = "";
                break;
            case "paramprompt":
                grabPrompt = true;
                prompt = ("");
                break;
            case "paramaltunit":
                grabUnit = true;
                unit = ("");
                break;
            case "factor":
                factorStr = ("");
                grabFactor = true;
                break;
            case "paramchoice":
                grabChoice = true;
                choiceStr = ("");
                if (attrs != null) {
                    for (int i = 0; i < attrs.getLength(); i++) {
                        String aName = attrs.getLocalName(i); // Attr name
                        if ("".equals(aName)) {
                            aName = attrs.getQName(i);
                        }
                        if (aName.equals("value")) {
                            choiceIndex = Integer.parseInt(attrs.getValue(i));
                        }
                    }
                }
                break;
            case "addend":
                grabAdder = true;
                adderStr = ("");
                break;
            case "id":
                grabId = true;
                idStr = ("");
                break;
        }

    }

    /**
     * Part of SAX processing that gets called when an ending xml tag is 
     * encountered. 
     * @param namespaceURI
     * @param qName qualified name
     * @param sName simple name
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void endElement(String namespaceURI,
            String sName,
            String qName
    )
            throws SAXException {
        String eName = sName; // element name
        if ("".equals(eName)) {
            eName = qName;
        }
        switch (eName) {
            case "paramlang":
                String parmName = (name);
                if (!isCropXml) // all operation parameters have the numeric id appended to prevent conflicts
                {
                    //chages by Isaac Haas
                    int intId = Integer.parseInt(idStr);
                    parmName = parmName.concat(Integer.toString(intId));
                }
                if (pNames.getParamDef(parmName) != null) {
                    pNames.setPromptName(parmName, prompt);
                    if (hasAltUnit) {
                        pNames.setAltUnit(parmName, unit);
                    }
                    if (hasAddEnd) {
                        pNames.setAddEnd(parmName, adder);
                    }
                    if (hasFactor) {
                        pNames.setFactor(parmName, factor);
                    }

                    if (lastChoice > 0) {
                        // choice list variable
                        for (int i = 0; i < lastChoice; i++) {
                            pNames.setChoice(parmName, choicesInx[i], choicesName[i]);
                        }
                    }
                } else {
                    String estr = "";
                    if (!isCropXml) {
                        estr = "Could not match parameter name in LANG and DEFN files: " + name + " in process/group " + idStr;
                    } else {
                        estr = "Could not match parameter name in LANG and DEFN files: " + name;
                    }
                    //System.out.println(estr);
                    ErrorSink.add(estr);
                }
                lastChoice = 0;
                break;
            case "paramname":
                grabName = false;
                name = name.trim();
                break;
            case "paramprompt":
                grabPrompt = false;
                prompt = prompt.trim();
                break;
            case "paramaltunit":
                grabUnit = false;
                unit = unit.trim();
                break;
            case "factor":
                grabFactor = false;
                factor = Float.parseFloat(factorStr);
                break;
            case "paramchoice":
                grabChoice = false;
                choicesInx[lastChoice] = choiceIndex;
                choicesName[lastChoice++] = choiceStr.trim();
                break;
            case "addend":
                grabAdder = false;
                adder = Float.parseFloat(adderStr);
                break;
            case "id":
                grabId = false;
                idStr = idStr.trim();
                break;
        }

    }

    /**
     * Part of SAX processing that gets called to get the contents inside an
     * xml tag. The calls to get the contents may not come in one chunk so we need
     * to accumulate caracter strings until the ending tag then the string can be assumed to
     * be complete.
     * @param buf
     * @param len
     * @param offset
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void characters(char buf[], int offset, int len)
            throws SAXException {
        String s = new String(buf, offset, len);
        if (grabName) {
            name = name.concat(s);
        } else if (grabPrompt) {
            prompt = prompt.concat(s);
        } else if (grabUnit) {
            unit = unit.concat(s);
            hasAltUnit = true;
        } else if (grabFactor) {
            factorStr = factorStr.concat(s);
            hasFactor = true;
        } else if (grabChoice) {
            choiceStr = choiceStr.concat(s);
        } else if (grabAdder) {
            adderStr = adderStr.concat(s);
            hasAddEnd = true;
        } else if (grabId) {
            idStr = idStr.concat(s);
        }

    }

}
