/*
 * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejte.ccl.reporter;

import org.xml.sax.*;
import org.xml.sax.ext.*;
import org.xml.sax.helpers.*;
import java.io.*;
import java.util.*;

public class ParseML{
    private String vendorParserClass = 
    "org.apache.xerces.parsers.SAXParser";
    public static boolean debug = false;
    boolean inTestcase = false;
    boolean inTestcaseID = false;
    boolean gotStatus = false;
    static Hashtable hash =  null;
    static Vector[] fileDiffs = null;
    String key = "";
    String value = "";

    public static void main(String args[]){
        ParseML pml = new ParseML();
        if(args.length<2){
            pml.usage();
        }
        hash = new Hashtable();
        int no_of_files = args.length;
        if(debug){
            System.out.println("number of files:"+no_of_files);
        }
        Hashtable[] filehash = new Hashtable[no_of_files];
        fileDiffs = new Vector[no_of_files];
        for(int i = 0; i<args.length; i++){              
            filehash[i] = new Hashtable();
            fileDiffs[i] = new Vector();
            fileDiffs[i].add("</u><b>File:"+args[i]+"</b></u><br>\n"); // add the filename to the vector
            System.out.println("parsing file #"+i);
            filehash[i] = pml.buildTree(args[i]);
            hash = null;
            hash = new Hashtable();
            if(debug){
                System.out.print("========================");
                System.out.println("Displaying hashtable # "+i);
                pml.displayHash(filehash[i]);
            }
        }                                
        pml.diffHash(filehash);
        pml.displayVectorArr(fileDiffs);
        System.out.print("writing diffs to file...");
        pml.writeDiffs(fileDiffs);
        System.out.println("done");
    }
    public Hashtable buildTree(String xmlURI){
        //hash = null;
        try{
            //Initialize a reader
            XMLReader reader = 
            XMLReaderFactory.createXMLReader(vendorParserClass);
            //Register Content Handler
            ContentHandler myContentHandler = new MyContentHandler();
            reader.setContentHandler(myContentHandler);

            //Parse
            InputSource inputSource = 
            new InputSource(new java.io.FileInputStream(new java.io.File(xmlURI)));
            reader.parse(inputSource);

        } catch(Throwable th){
            th.printStackTrace();
        }
        return hash;
    }

    class MyContentHandler implements ContentHandler{
        private Locator locator;
        public void setDocumentLocator(Locator locator){
            this.locator = locator;
        }
        public void startDocument() throws SAXException{
            //initialize a 2D vector here
        }
        public void endDocument() throws SAXException{
        }
        public void processingInstruction(String target, String data)
            throws SAXException{
            // add target and data to the 2D vector
        }
        public void startPrefixMapping(String prefix, String uri){
        }
        public void endPrefixMapping(String prefix){
        }
        public void startElement(String namespaceURI, String localName, 
                                 String qName, Attributes atts)
            throws SAXException{
            // add the local name into vector
            if(localName.equals("testcase")){
                inTestcase = true;
            }
            if(localName.equals("id") && (inTestcase)){
                inTestcaseID = true;
                if(debug){
                    System.out.println("inside testcase id.");
                }
            }
            // assuming that when its time to get the status, the value for the keys would have been obtained. 
            if(localName.equals("status") && (inTestcase)){
                //get attributes: pass/fail
                if(debug){
                    System.out.println("getting testcase status...");                   
                }
                value = atts.getValue(0).trim();
                if((key!=null) && (!(key.equals(""))) && (value!=null) && (!value.equals(""))){
                    if(debug){
                        System.out.println("Key["+key+"] has value["+value+"]");                   
                    }
                    hash.put(key,value);
                    gotStatus = true;
                    key = ""; 
                    value = "";
                } 
                else{
                    if(key == null || key.equals("")){
                        System.out.println("invalid key!");
                    }
                    if(value== null || value.equals("")){
                        System.out.println("invalid value!");
                    }             
                }
            }
        }
        public void endElement(String namespaceURI, String localName, String qName)
            throws SAXException{
            if(localName.equals("testcase")){
                inTestcase = false;
                if(debug){
                        System.out.println("Outside testcase tag");                   
                }
            }
            if(localName.equals("id") && (inTestcase)){
                inTestcaseID = false;
                if(debug){
                    System.out.println("Outside testcase-ID tag");                   
                }  /*
                key = key.trim();
                value = value.trim();
                if((key!=null) && (value!=null) && 
                   (!(value.equals(""))) && (!(key.equals("")))){

                }    */
            }
        }
        public void characters(char[] ch, int start, int length)
            throws SAXException{
            String s = new String(ch, start, length);
            if(debug){
                System.out.print("\nvalue of start index= "+start+", ");
                System.out.print("length of charectars = "+length+", ");
                System.out.println("string = ["+s+"]");
            }
            if(inTestcaseID){
                key += s.trim();
                if((key!=null) && (!key.equals(""))){
                    if(debug){
                        System.out.println("TestCase ID:"+key);
                    }
                }
            }
        }
        public void ignorableWhitespace(char[] ch, int start, int length)
            throws SAXException{
        }
        public void skippedEntity(String name) throws SAXException{
            System.out.println("Skipped entity is:"+name);
        }  
    }
    /*======= End of Inner Class Definition ================*/

    public void displayHash(Hashtable hashtable){ 
        for (Enumeration e = hashtable.keys() ; e.hasMoreElements() ;) {
            String keyval = (String)e.nextElement();
            System.out.println(keyval +":"+hashtable.get(keyval));
        }
    } 

    public void displayVector(Vector v){
        for(int i=0; i<v.size(); i++){
            System.out.println((String)v.get(i));
        }
    }

    public void displayVectorArr(Vector[] v){
        for (int i = 0; i<v.length; i++){
            displayVector(v[i]);
        }
    }

    public void writeDiffs(Vector[] v){
        try{
            File inputfile = new File("fileDiffs.html");
            FileWriter fw = new FileWriter(inputfile);
            String filecontent = "<h3>File Diff Output</h3><hr>\n";            
            for(int i = 0; i<v.length ; i++){    
                for(int j = 0; j<v[i].size(); j++){
                    filecontent += v[i].get(j)+"<br>\n";
                }
                filecontent += "<hr>\n";
            }
            fw.write(filecontent);
            fw.close();
        } catch(FileNotFoundException fnfe){
            System.out.println("File is not present. \n"+
                               "Please check the file name and try again");
        } catch(Exception ex){
            ex.printStackTrace();
        }        
    }

    public Vector getKeyList(Hashtable[] hashes){
        int hashtables = hashes.length;
        Vector allkeys= new Vector();
        Vector[] hashVecs = new Vector[hashtables];
        for(int i=0; i<hashtables; i++){            
            hashVecs[i] = new Vector((Collection)hashes[i].keySet());
        }
        allkeys = getUnion(hashVecs);
        return allkeys;
    }

    public Vector getUnion(Vector[] v){
        Vector union = new Vector();
        for(int i=0; i<v.length; i++){
            for(int j=0; j<v[i].size(); j++){
                if(!union.contains(v[i].get(j))){
                    union.add(v[i].get(j));
                }//end if
            }//end inner-for
        }// end outer-for
        return union;
    }// end method getUnion

    public void diffHash(Hashtable[] hashes){
        int hashtables = hashes.length;
        if(debug){
            System.out.println("total hashtables to diff:"+hashtables);
        }
        int bigHash = 0; // take the first hashtable as the golden file.
        /*Get a list of most keys*/ 
        Vector keylist = new Vector();
        keylist = getKeyList(hashes);
        /*Start comparing all other hashtable elements to this golden list of testcases*/

        int totalkeys = keylist.size();
        if(debug){
            System.out.println("Total number of testcases gathered: "+totalkeys);
        }
        for(int keyno=0; keyno<totalkeys; keyno++){ 
            String keyObj = (String)keylist.get(keyno);
            Object val = null;
            Object bigHashVal = null;
            // for all hashtables in the array...
            if(debug){
                System.out.println("checking out key:"+keyObj);
            }
            for(int i = 0; i<hashtables ; i++){               
                if(i==bigHash){ 
                    continue;
                }
                // key exists
                if((bigHashVal=hashes[bigHash].get(keyObj))!=null){ // key exists in bigHash
                    if((val = hashes[i].get(keyObj))!=null){
                        if (val.equals(bigHashVal)){
                            // key and value pair match the golden file
                            continue;
                        } else {
                            // key exists but the values are different
                            // add it into both the vectors, if not already there. 
                            String diffObj = "<font color=blue>"+keyObj+
                                " has an inconsistent status:"+(String)val+
                                "</font>"; 
                            String bigdiffObj =  "<font color=blue>"+keyObj+
                                " has an inconsistent status:"+(String)bigHashVal+
                                "</font>";
                            if(!fileDiffs[i].contains(diffObj)){
                                fileDiffs[i].add(diffObj);
                            }
                            if(!fileDiffs[bigHash].contains(bigdiffObj)){
                                fileDiffs[bigHash].add(bigdiffObj);
                            }
                        }   
                    } else {
                        // key doesn't exist
                        /*add it into the vector for smaller tables, if not already there.*/   
                        String diffObj =  "<font color=red>"+keyObj+
                            " testcase is missing </font>";
                        if(!fileDiffs[i].contains(diffObj)){
                            fileDiffs[i].add(diffObj);
                        }// end missing-key if
                    }   // end missing-key else
                    // end key-exists if in bighash
                } else {
                    // add the missing key into the vector for bighash
                    String bigdiffObj = "<font color=red>"+keyObj+
                        " testcase is missing </font>";
                    if(!fileDiffs[bigHash].contains(bigdiffObj)){
                        fileDiffs[bigHash].add(bigdiffObj);
                    }// end missing-key if                        
                }
            } // end for-loop for going through the hashtable array
        } // end for-loop for keys in the bigHash hashtable
    } // end diff-hash method              

    public void usage(){    
        String usageStr = "Usage:\n java ParseML <xml_file_1> <xml_file_2> <xml_file_3>..."+
            "\n\tThis Utility will let you 'diff' multiple xml"+
            "\n\t files and produce a fileDiff.html file in the "+
            "\n\t directory where this file is run from."+
            "\n\tDiff results are produced only by matching the contents "+
            "\n\tof the xml trees and not by comparing text characters."+
            "\n\n\tThis program takes arguments of two or more 'well_formed_xml' files.";
        System.out.println(usageStr);
        System.exit(0);
    }
}
