package usda.weru.mcrew;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileReader;
import de.schlichtherle.io.FileWriter;
import java.io.BufferedReader;
import java.io.IOException;

import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;



class SkeletonUpdater {
    private static final Logger LOGGER=Logger.getLogger(SkeletonUpdater.class);
    List <String> opdates;
    List <String> opnames;
    List <String> vegnames;
    Integer rotationYears;
    public String notes="";

    SkeletonUpdater() {

    }

    //
    // readWEPSManBrief()
    //
    // Reads a WEPS management file and saves the dates, operations and crops in vectors. This will handle both management
    // file versions 1.1 and 1.2
    //
    public boolean readWEPSManBrief(String wepsLongName) {

        opnames=new Vector<String>();
        opdates=new Vector<String>();
        vegnames=new Vector<String>();
        rotationYears=1;
        String sSTART="start";
        BufferedReader br=null;
        try {
            br=new BufferedReader(new FileReader(wepsLongName));
            String temp;
            //loop to find out the 'D'&'O' pair, then set to DOM tree
            temp=br.readLine();
            while (temp != null) {
                temp=temp.trim();
                if (temp.length() == 0) {
                    temp=br.readLine();
                    continue;
                }
                if (temp.startsWith("*START")) {
                    int rotationIndex=temp.toLowerCase().indexOf(sSTART) + sSTART.length();
                    String rotationStr=temp.substring(rotationIndex).trim();
                    if (rotationStr.endsWith("<")) {
                        rotationStr=rotationStr.substring(0, rotationStr.length() - 2);
                    }
                    rotationStr=rotationStr.trim();
                    rotationYears=(Integer.valueOf(rotationStr));
                }
                if (temp.charAt(0) == 'D') {
                    String txtdate=temp.substring(2).trim();
                    if (txtdate.endsWith("<")) {
                        txtdate=txtdate.substring(0, txtdate.length() - 2);
                    }
                    txtdate=txtdate.trim();
                    // switch the day/month to month/day
                    StringTokenizer thedate=new StringTokenizer(txtdate, "/");
                    String day=thedate.nextToken();
                    String month=thedate.nextToken();
                    String year=thedate.nextToken();
                    String skeldate=month + "/" + day + "/" + year;

                    //rotationYears = new Integer(year);

                    temp=br.readLine();
                    if(temp != null){
                    String txtname=temp.substring(5).trim();
                        if (txtname.endsWith("<")) {
                            txtname=txtname.substring(0, txtname.length() - 2);
                        }
                        txtname=txtname.trim();
                        opnames.add(txtname);
                    }                 
                    else{
                        LOGGER.warn("Unexpected null value.");
                    }
                    
                    opdates.add(skeldate);
                    vegnames.add("");

                    temp=br.readLine();
                    String g03="G 03";
                    while (temp != null && temp.charAt(0) != 'D') {
                        if (temp.startsWith(g03)) {
                            temp=br.readLine();//need to confirm if the name is "no crop" or not.
                            if(temp != null){
                                String subvegname=temp.substring(2).trim();
                                if (subvegname.endsWith("<")) {
                                    subvegname=subvegname.substring(0, subvegname.length() - 2);
                                }
                                subvegname=subvegname.trim();
                                int index=vegnames.size();
                                vegnames.set(index - 1, subvegname);
                            }
                            else{
                                LOGGER.warn("Unexpected null value.");
                            }
                        }
                        temp=br.readLine();
                    }
                } else if (temp.charAt(0) == 'N') {//Notes field
                    if (temp.length() > 2 && temp.substring(2) != null) {
                        notes=notes + (temp.substring(2)) + "\n";
                    }
                    temp=br.readLine();

                } else {
                    temp=br.readLine();
                }
            }
        } catch (IOException e) {
            //System.err.println("RunFileData: " + e);
            return false;
        } finally {
            try {
                br.close();
            } catch (Exception e) {
                LOGGER.error("Error closing file stream.", e);
            }
        }

        return true;

    }

    //
    // writeSkeletonXMLFile()
    //
    // Writes out an NRCS XML skeleton file from the data that was read in.
    //
    public boolean writeSkeletonXMLFile(String filename) {

        Node root;        
        //Saftey check, build required directory structure        
        File dir = (File)new File(filename).getParentFile();
        if (!dir.exists()){
            boolean created = dir.mkdirs();
            if (!created){
                LOGGER.error("Unable to create required directory structure: " + dir.getAbsolutePath());
                return false;
            }
        }
        String nonEscapingElements[]={XMLConstants.soperationname, XMLConstants.sname};

        try {
            //DocumentType manDocType = XMLDoc.createDocument(XMLConstants.smanagement_skeleton);
            //Document wepsmanDoc = XMLDoc.mDOMImpl.createDocument(null, XMLConstants.smanagement,null);

            Document wepsmanDoc=XMLDoc.createDocument(XMLConstants.smanagement_skeleton);

            root=wepsmanDoc.getDocumentElement();

            ((Element) root).setAttribute("ver", "1.0");    //Currently hardcoded until we have a better schema defined.
            ((Element) root).setAttribute("prog", usda.weru.util.Application.WEPS.getName());





            //Notes tag                        
            Node nodeNotes=wepsmanDoc.createElement(XMLConstants.snotes);
            XMLDoc.setTextData(nodeNotes, notes, wepsmanDoc);
            root.appendChild(nodeNotes);

            //Rotation Years tag
            Node rotyearsNode=wepsmanDoc.createElement(XMLConstants.srotationyears);
            XMLDoc.setTextData(rotyearsNode, rotationYears.toString(), wepsmanDoc);
            root.appendChild(rotyearsNode);



            File f=new File(filename);

            String shortName=f.getName();
            int index=shortName.lastIndexOf(".");
            String basename=shortName;
            if (index > 0) {
                basename=shortName.substring(0, index);
            }

            Node nameNode=wepsmanDoc.createElement(XMLConstants.sname);
            XMLDoc.setTextData(nameNode, basename, wepsmanDoc);
            root.appendChild(nameNode);

            Node operations=wepsmanDoc.createElement(XMLConstants.soperationskel);

            for (int i=0; i < opdates.size(); i++) {
                Node wepsOp=wepsmanDoc.createElement(XMLConstants.sopskel);
                Node date=wepsmanDoc.createElement(XMLConstants.sdate);
                XMLDoc.setTextData(date, (String) opdates.get(i), wepsmanDoc);
                wepsOp.appendChild(date);
                Node opNameNode=wepsmanDoc.createElement(XMLConstants.sname);
                XMLDoc.setTextData(opNameNode, (String) opnames.get(i), wepsmanDoc);
                wepsOp.appendChild(opNameNode);
                String plant=(String) vegnames.get(i);
                if (plant.length() > 0) {
                    Node vegNode=wepsmanDoc.createElement(XMLConstants.svegskel);
                    Node vegName=wepsmanDoc.createElement(XMLConstants.sname);
                    XMLDoc.setTextData(vegName, plant, wepsmanDoc);
                    vegNode.appendChild(vegName);
                    wepsOp.appendChild(vegNode);
                }
                operations.appendChild(wepsOp);
            }

            root.appendChild(operations);

            OutputFormat format=new OutputFormat(wepsmanDoc);
            format.setIndenting(true);
            format.setIndent(XMLConstants.INDENT);
            format.setEncoding(XMLConstants.sEncoding);
            format.setNonEscapingElements(nonEscapingElements);
            format.setMediaType(XMLConstants.sMediaType);
            format.setVersion(XMLConstants.sVersion);
            FileWriter fw=new FileWriter(filename);

            XMLSerializer serializer=new XMLSerializer(fw, format);
            serializer.serialize(wepsmanDoc);

            fw.close();
         } catch (DOMException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            //e.printStackTrace();
            // Could not write the file for some reason
            return false;
        }

        return true;


    }

    //
    // getDates()
    //
    // Returns verctor of date strings read from management file
    //
    public List <String> getDates() {
        return opdates;
    }

    // 
    // getOperations()
    //
    // Returns vector of operation strings read from management file
    //
    public List <String> getOperations() {
        return opnames;
    }

    // 
    // getCrops()
    //
    // Returns vector of crop strings read from management file. On dates with no
    // vegetation the string is empty ""
    //
    public List <String> getCrops() {
        return vegnames;
    }
}
