//Instrumenteur HTML pour autre programme à venir.
//http://www.jroller.com/page/kame/
//Copyright (C) 2004 Damien Bonvillain
//
// Dépend de HTMLParser: http://htmlparser.sourceforge.net 
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//

package net.cynicalturtle.divers.html;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.lexer.nodes.TagNode;
import org.htmlparser.tags.CompositeTag;
import org.htmlparser.tags.HeadTag;
import org.htmlparser.tags.Html;
import org.htmlparser.tags.ScriptTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.util.SimpleNodeIterator;

public class Instrumenteur {
	public static void main(String[] argv) {
		if (argv.length == 0) {
			System.out.println("Entrez un nom de fichier");
			System.exit(1);
		}

		File fIn = new File(argv[0]);
		try {
			File fOut = new File(fIn.getCanonicalPath() + ".instr.htm");

			Parser parser = new Parser(fIn.getCanonicalPath());

			Html ht = (Html) parser.extractAllNodesThatAre(Html.class)[0];
			NodeList nl = new NodeList();
			
			// on vire les <script>
			ht.collectInto(nl, new NodeClassFilter(ScriptTag.class));
			for (SimpleNodeIterator sni = nl.elements(); sni.hasMoreNodes();) {
				Node noeud = sni.nextNode();
				CompositeTag parent = (CompositeTag) noeud.getParent();
				parent.removeChild(parent.findPositionOf(noeud));
			}
			nl.removeAll();

			// ici les Filter sont en fait utilisés en tant que Visitor
			// parce que... c'est plus simple, voilà
			// on vire les onBidule
			ht.collectInto(null, new JSNodeFilter());
			// et on rajoute notre javascript à nous
			ht.collectInto(null, new InstrumentationFilter());
			
			// et tout ça dans un fichier...
			BufferedWriter bw = new BufferedWriter(new FileWriter(fOut));
			bw.write(ht.toHtml());
			bw.close();
		} catch (IOException ioe) {
			System.err.println(ioe.getLocalizedMessage());
		} catch (ParserException e) {
			e.printStackTrace();
		}

	}

	private static class JSNodeFilter implements NodeFilter {
		public boolean accept(Node node) {
			boolean result = false;
			if (node instanceof TagNode) {
				TagNode tn = (TagNode) node;
				Collection coll = tn.getAttributes().keySet();
				for (Iterator it = coll.iterator(); it.hasNext();) {
					String attr = (String) it.next();
					if (attr.startsWith("ON")) {
						tn.removeAttribute(attr);
					}
				}
			}

			return false;
		}
	}

	private static class InstrumentationFilter implements NodeFilter {
		private boolean jsMis = false;
		public boolean accept(Node node) {
			if (node instanceof TagNode) {
				TagNode tn = (TagNode) node;
				if (!tn.isEndTag()) {
					tn.setAttribute("n", "1");

					if (!jsMis && tn instanceof HeadTag) {
						HeadTag ht = (HeadTag) tn;
						NodeList nl = ht.getChildren();
						ScriptTag st = new ScriptTag();
						st.setScriptCode(
							"function A(n,g){var p=n.parentNode,t=n.tagName;if(!p)return '';if(!t)return A(p,g);if(n.nodeType!=9)if(!((n.getAttribute&&n.getAttribute('n'))||(n.hasAttribute&&n.hasAttribute('n'))))return A(p,g);var T=t.toUpperCase();var count=0;var n2;for(j=0;j<p.childNodes.length;++j){n2=p.childNodes[j];if(n2==n){break;}else if(n2.nodeType==1&&n2.tagName.toUpperCase()==T){++count;}}return A(p,'/')+T+'['+count+']'+g;}function msg(e){e=e?e:event;var s,g=e.target;g=g?g:e.srcElement;return s;}document.onmouseover=function(e){window.status=msg(e);return true;};document.onclick=function(e){e=e?e:event;if((e.which==1||e.button==0)&&e.ctrlKey){var s=msg(e);w=self.open();w.document.write(s);w.document.close();}return false;};");
						nl.add(st);
						TagNode nt = new TagNode();
						nt.setTagName("/SCRIPT");
						nl.add(nt);
						ht.setChildren(nl);
						jsMis = true;
					}
				}

			}
			return false;
		}
	}
}
