/**
 * File: Test.java
 *
 * Author: David Hay (dhay@localmatters.com)
 * Creation Date: Apr 12, 2010
 * Creation Time: 10:26:14 AM
 *
 * Copyright 2010 Local Matters, Inc.
 * All Rights Reserved
 *
 * Last checkin:
 *  $Author$
 *  $Revision$
 *  $Date$
 */
package org.lesscss4j;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.Tree;
import org.lesscss4j.parser.Css21Lexer;
import org.lesscss4j.parser.Css21Parser;

import static org.lesscss4j.parser.Css21Lexer.*;

public class Test {
    public static void main(String[] args) throws Exception {
        if (args.length < 1) {
            System.err.println("Usage: java " + Test.class.getName() + " <filename>");
            System.exit(-1);
        }
        new Test().processFile(args[0]);
    }

    public void processFile(String filename) throws Exception {
        Css21Lexer lexer = new Css21Lexer(new ANTLRFileStream(filename, "UTF-8"));
        Css21Parser parser = new Css21Parser(new CommonTokenStream(lexer));
        Css21Parser.styleSheet_return result = parser.styleSheet();

        StringWriter writer = new StringWriter();
        Tree tree = (Tree) result.getTree();

        processStylesheet(tree, writer);

        System.out.println(writer.toString());
//        System.out.println(treeToString((Tree)result.getTree()));
//        System.out.println(((CommonTree) result.getTree()).toStringTree());
/*
        DOTTreeGenerator gen = new DOTTreeGenerator();
        StringTemplate st = gen.toDOT(((Tree) result.getTree()));
        System.out.println(st);
*/

    }

    protected void processStylesheet(Tree tree, Writer writer) throws IOException {
        for (int idx = 0, numChildren = tree.getChildCount(); idx < numChildren; idx++) {
            Tree child = tree.getChild(idx);
            switch (child.getType()) {
                case CHARSET:
                    processCharset(child, writer);
                    break;
                case IMPORT:
                    processImport(child, writer);
                    break;
                case RULESET:
                    processRuleset(child, writer);
                    break;
                case WS:
                    break;
                case EOF:
                    break;
                default:
                    throw new IllegalStateException(
                        String.format("Unexpected stylesheet child [%d] %s", child.getType(), child.toString()));
            }
        }
    }

    protected void processCharset(Tree tree, Writer writer) throws IOException {
        writer.write("@charset ");
        writer.write(tree.getChild(0).toString());
        writer.write(";");
    }

    protected void processImport(Tree tree, Writer writer) throws IOException {
        writer.write("@import ");
        writer.write(tree.getChild(0).toString());
        writer.write(";");
    }

    protected void processRuleset(Tree tree, Writer writer) throws IOException {
        int selectorCount = 0;
        int declarationCount = 0;
        // todo: preprocess to find all the declarations....count of 0 == suppress
        for (int idx = 0, numChildren = tree.getChildCount(); idx < numChildren; idx++) {
            Tree child = tree.getChild(idx);
            switch (child.getType()) {
                case SELECTOR:
                    if (selectorCount > 0) {
                        writer.write(",");
                    }
                    processSelector(child, writer);
                    selectorCount++;
                    break;
                case DECLARATION:
                    if (declarationCount == 0) {
                        writer.write("{");
                    }
                    processDeclaration(child, writer);
                    declarationCount++;
                    break;
                case WS:
                    break;
                default:
                    throw new IllegalStateException(
                        String.format("Unexpected ruleset child [%d] %s", child.getType(), child.toString()));
            }
        }
        if (declarationCount > 0) {
            writer.write("}");
        }
    }

    protected void processDeclaration(Tree tree, Writer writer) throws IOException {
        Tree property = tree.getChild(0);
        Tree propValue = property.getChild(0);
        if (propValue.getType() == STAR) {
            writer.write('*');
            propValue = property.getChild(1);
        }
        writer.write(property.toString());
        writer.write(":");
        for (int idx = 0, numChildren = propValue.getChildCount(); idx < numChildren; idx++) {
            Tree child = propValue.getChild(idx);
            if (child.getType() == WS) {
                writer.write(" ");
            }
            else {
                writer.write(child.toString());
            }
        }
        writer.write(";");
    }

    protected void processSelector(Tree tree, Writer writer) throws IOException {
        for (int idx = 0, numChildren = tree.getChildCount(); idx < numChildren; idx++) {
            Tree child = tree.getChild(idx);
            if (child.getType() == WS) {
                writer.write(" ");
            }
            else {
                writer.write(child.toString());
            }
        }
    }


    protected String treeToString(Tree tree) {
        StringBuilder builder = new StringBuilder();
        treeToString(tree, builder, 0);
        return builder.toString();
    }

    protected void treeToString(Tree tree, StringBuilder builder, int level) {
        for (int idx = 0; idx < level*2; idx++) {
            builder.append(' ');
        }
        builder.append(tree.toString());
        builder.append('\n');

        for (int idx = 0, numChildren = tree.getChildCount(); idx < numChildren; idx++) {
            treeToString(tree.getChild(idx), builder, level + 1);
        }
    }
}

@@ -954,32 +954,88 @@
 ows Exception %7B%0A
+        System.out.println(%22Reading file:%22 + filename);%0A
         Css21Lex
@@ -1097,24 +1097,24 @@
  %22UTF-8%22));%0A
-
         Css2
@@ -1736,32 +1736,256 @@
 st);%0A*/%0A%0A    %7D%0A%0A
+    protected String formatNode(String prefix, Tree node) %7B%0A        return String.format(%22%25s %5B%25d=%25s%5D %25s%22,%0A                             prefix, node.getType(), Css21Parser.tokenNames%5Bnode.getType()%5D, node.toString());%0A    %7D%0A%0A
     protected vo
@@ -2540,32 +2540,147 @@
          break;%0A
+                case MEDIA_SYM:%0A                    writer.write(%22/* TODO: @media */%22);%0A                    break;%0A
                 
@@ -2849,46 +2849,18 @@
 ion(
-%0A                        String.
 format
+Node
 (%22Un
@@ -2888,52 +2888,17 @@
 hild
- %5B%25d%5D %25s%22, child.getType(), child.toString()
+:%22, child
 ));%0A
@@ -4391,46 +4391,18 @@
 ion(
-%0A                        String.
 format
+Node
 (%22Un
@@ -4427,52 +4427,17 @@
 hild
- %5B%25d%5D %25s%22, child.getType(), child.toString()
+:%22, child
 ));%0A

Clean up error reporting & display token name in errors (from Css21Parser.tokenNames) Support for @media (sort of)