/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.resources.css;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.resources.css.ast.CssDef;
import com.google.gwt.resources.css.ast.CssEval;
import com.google.gwt.resources.css.ast.CssExternalSelectors;
import com.google.gwt.resources.css.ast.CssFontFace;
import com.google.gwt.resources.css.ast.CssIf;
import com.google.gwt.resources.css.ast.CssMediaRule;
import com.google.gwt.resources.css.ast.CssNoFlip;
import com.google.gwt.resources.css.ast.CssNode;
import com.google.gwt.resources.css.ast.CssPageRule;
import com.google.gwt.resources.css.ast.CssProperty;
import com.google.gwt.resources.css.ast.CssProperty.DotPathValue;
import com.google.gwt.resources.css.ast.CssProperty.FunctionValue;
import com.google.gwt.resources.css.ast.CssProperty.IdentValue;
import com.google.gwt.resources.css.ast.CssProperty.ListValue;
import com.google.gwt.resources.css.ast.CssProperty.NumberValue;
import com.google.gwt.resources.css.ast.CssProperty.StringValue;
import com.google.gwt.resources.css.ast.CssProperty.TokenValue;
import com.google.gwt.resources.css.ast.CssProperty.Value;
import com.google.gwt.resources.css.ast.CssRule;
import com.google.gwt.resources.css.ast.CssSelector;
import com.google.gwt.resources.css.ast.CssSprite;
import com.google.gwt.resources.css.ast.CssStylesheet;
import com.google.gwt.resources.css.ast.CssUnknownAtRule;
import com.google.gwt.resources.css.ast.CssUrl;
import com.google.gwt.resources.css.ast.HasNodes;
import com.google.gwt.resources.css.ast.HasProperties;
import com.google.gwt.resources.ext.ResourceGeneratorUtil;

import org.w3c.css.sac.AttributeCondition;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.CharacterDataSelector;
import org.w3c.css.sac.CombinatorCondition;
import org.w3c.css.sac.Condition;
import org.w3c.css.sac.ConditionalSelector;
import org.w3c.css.sac.ContentCondition;
import org.w3c.css.sac.DescendantSelector;
import org.w3c.css.sac.DocumentHandler;
import org.w3c.css.sac.ElementSelector;
import org.w3c.css.sac.ErrorHandler;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.LangCondition;
import org.w3c.css.sac.LexicalUnit;
import org.w3c.css.sac.NegativeCondition;
import org.w3c.css.sac.NegativeSelector;
import org.w3c.css.sac.PositionalCondition;
import org.w3c.css.sac.ProcessingInstructionSelector;
import org.w3c.css.sac.SACMediaList;
import org.w3c.css.sac.Selector;
import org.w3c.css.sac.SelectorList;
import org.w3c.css.sac.SiblingSelector;
import org.w3c.flute.parser.Parser;

import java.io.IOException;
import java.io.StringReader;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Generates a CssStylesheet from the contents of a URL.
 */
@SuppressWarnings("unused")
public class GenerateCssAst {

  /**
   * Maps SAC CSSParseExceptions into a TreeLogger. All parsing errors will be
   * recorded in a single TreeLogger branch, which will be created only if a
   * loggable error message is emitted.
   */
  private static class Errors implements ErrorHandler {
    /**
     * A flag that controls whether or not the exec method will fail.
     */
    private boolean fatalErrorEncountered;
    private TreeLogger logger;
    private final TreeLogger parentLogger;

    /**
     * Constructor.
     *
     * @param parentLogger the TreeLogger that should be branched to produce the
     *          CSS parsing messages.
     */
    public Errors(TreeLogger parentLogger) {
      this.parentLogger = parentLogger;
    }

    public TreeLogger branch(TreeLogger.Type type, String message) {
      return branch(type, message, null);
    }

    public TreeLogger branch(TreeLogger.Type type, String message, Throwable t) {
      return logOrBranch(type, message, t, true);
    }

    public void error(CSSParseException exception) throws CSSException {
      // TODO Since this indicates a loss of data, should this be a fatal error?
      log(TreeLogger.WARN, exception);
    }

    public void fatalError(CSSParseException exception) throws CSSException {
      log(TreeLogger.ERROR, exception);
    }

    public void log(TreeLogger.Type type, String message) {
      log(type, message, null);
    }

    public void log(TreeLogger.Type type, String message, Throwable t) {
      logOrBranch(type, message, t, false);
    }

    public void warning(CSSParseException exception) throws CSSException {
      log(TreeLogger.DEBUG, exception);
    }

    private void log(TreeLogger.Type type, CSSParseException e) {
      log(type, "Line " + e.getLineNumber() + " column " + e.getColumnNumber()
          + ": " + e.getMessage());
    }

    private TreeLogger logOrBranch(TreeLogger.Type type, String message,
        Throwable t, boolean branch) {
      fatalErrorEncountered |= type == TreeLogger.ERROR;
      if (parentLogger.isLoggable(type)) {
        maybeBranch();
        if (branch) {
          return logger.branch(type, message, t);
        } else {
          logger.log(type, message, t);
          return null;
        }
      } else {
        return TreeLogger.NULL;
      }
    }

    private void maybeBranch() {
      if (logger == null) {
        logger = parentLogger.branch(TreeLogger.INFO,
            "The following problems were detected");
      }
    }
  }

  /**
   * Maps the SAC model into our own CSS AST nodes.
   */
  private static class GenerationHandler implements DocumentHandler {
    /**
     * The stylesheet that is being composed.
     */
    private final CssStylesheet css = new CssStylesheet();

    /**
     * Accumulates CSS nodes as they are created.
     */
    private final Stack<HasNodes> currentParent = new Stack<HasNodes>();

    /**
     * Accumulates CSS properties as they are seen.
     */
    private HasProperties currentRule;

    /**
     * Records references to {@code @def} rules.
     */
    private final Map<String, CssDef> defs = new HashMap<String, CssDef>();

    /**
     * Used when parsing the contents of meta-styles.
     */
    private final Errors errors;

    /**
     * Used by {@link #startSelector(SelectorList)} to suppress the creation of
     * new CssRules in favor of retaining {@link #currentRule}.
     */
    private boolean nextSelectorCreatesRule = true;

    public GenerationHandler(Errors errors) {
      this.errors = errors;
      currentParent.push(css);
    }

    public void comment(String text) throws CSSException {
      // Ignore comments
      // TODO Should comments be retained but not generally printed?
    }

    public void endDocument(InputSource source) throws CSSException {
    }

    public void endFontFace() throws CSSException {
    }

    public void endMedia(SACMediaList media) throws CSSException {
      currentParent.pop();
    }

    public void endPage(String name, String pseudoPage) throws CSSException {
    }

    public void endSelector(SelectorList selectors) throws CSSException {
    }

    /**
     * Reflectively invoke a method named parseRule on this instance.
     */
    public void ignorableAtRule(String atRule) throws CSSException {
      int idx = atRule.indexOf(" ");
      if (idx == -1) {
        // Empty rule like @foo;
        addNode(new CssUnknownAtRule(atRule));
        return;
      }
      String ruleName = atRule.substring(1, idx);
      String methodName = "parse" + (Character.toUpperCase(ruleName.charAt(0)))
          + ruleName.substring(1).toLowerCase();
      try {
        Method parseMethod = getClass().getDeclaredMethod(methodName,
            String.class);
        parseMethod.invoke(this, atRule);
      } catch (NoSuchMethodException e) {
        // A rule like @-webkit-keyframe {...} that we can't process
        addNode(new CssUnknownAtRule(atRule));
      } catch (IllegalAccessException e) {
        errors.log(TreeLogger.ERROR, "Unable to invoke parse method ", e);
      } catch (InvocationTargetException e) {
        Throwable cause = e.getCause();

        if (cause instanceof CSSException) {
          // Unwind a CSSException normally
          throw (CSSException) cause;
        } else if (cause != null) {
          // Otherwise, report the message nicely
          TreeLogger details = errors.branch(TreeLogger.ERROR,
              cause.getMessage());
          details.log(TreeLogger.DEBUG, "Full stack trace", cause);
        } else {
          TreeLogger details = errors.branch(TreeLogger.ERROR,
              "Unknown failure parsing " + ruleName);
          details.log(TreeLogger.DEBUG, "Full stack trace", e);
        }
      }
    }

    public void importStyle(String uri, SACMediaList media,
        String defaultNamespaceURI) throws CSSException {
    }

    public void namespaceDeclaration(String prefix, String uri)
        throws CSSException {
    }

    public void property(String name, LexicalUnit value, boolean important)
        throws CSSException {
      List<Value> values = new ArrayList<Value>();
      if (value != null) {
        extractValueOf(values, value);
      }
      currentRule.getProperties().add(
          new CssProperty(escapeIdent(name), new ListValue(values), important));
    }

    public void startDocument(InputSource source) throws CSSException {
    }

    public void startFontFace() throws CSSException {
      CssFontFace rule = new CssFontFace();
      addNode(rule);
      currentRule = rule;
    }

    public void startMedia(SACMediaList media) throws CSSException {
      CssMediaRule r = new CssMediaRule();
      for (int i = 0; i < media.getLength(); i++) {
        r.getMedias().add(media.item(i));
      }

      pushParent(r);
    }

    public void startPage(String name, String pseudoPage) throws CSSException {
      CssPageRule r = new CssPageRule();
      // name appears to be unused in CSS2
      r.setPseudoPage(pseudoPage);
      addNode(r);
      currentRule = r;
    }

    public void startSelector(SelectorList selectors) throws CSSException {
      CssRule r;

      if (nextSelectorCreatesRule) {
        r = new CssRule();
        addNode(r);
        currentRule = r;
      } else {
        r = (CssRule) currentRule;
        nextSelectorCreatesRule = true;
      }

      for (int i = 0; i < selectors.getLength(); i++) {
        r.getSelectors().add(new CssSelector(valueOf(selectors.item(i))));
      }
    }

    void parseDef(String atRule) {
      String value = atRule.substring(4, atRule.length()).trim();

      InputSource s = new InputSource();
      s.setCharacterStream(new StringReader(value));
      Parser parser = new Parser();
      parser.setErrorHandler(errors);

      final List<Value> values = new ArrayList<Value>();
      parser.setDocumentHandler(new PropertyExtractor(values));

      try {
        String dummy = "* { prop : " + value + "}";
        parser.parseStyleSheet(new InputSource(new StringReader(dummy)));
      } catch (IOException e) {
        assert false : "Should never happen";
      }

      if (values.size() < 2) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "@def rules must specify an identifier and one or more values",
            null);
      }

      IdentValue defName = values.get(0).isIdentValue();

      if (defName == null) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "First lexical unit must be an identifier", null);
      }

      /*
       * Replace any references to previously-seen @def constructs. We do
       * expansion up-front to prevent the need for cycle-detection later.
       */
      for (ListIterator<Value> it = values.listIterator(1); it.hasNext();) {
        IdentValue maybeDefReference = it.next().isIdentValue();
        if (maybeDefReference != null) {
          CssDef previousDef = defs.get(maybeDefReference.getIdent());
          if (previousDef != null) {
            it.remove();
            for (Value previousValue : previousDef.getValues()) {
              it.add(previousValue);
            }
          }
        }
      }

      CssDef def = new CssDef(defName.getIdent());
      def.getValues().addAll(values.subList(1, values.size()));
      addNode(def);

      defs.put(defName.getIdent(), def);
    }

    /**
     * The elif nodes are processed as though they were {@code @if} nodes. The
     * newly-generated CssIf node will be attached to the last CssIf in the
     * if/else chain.
     */
    void parseElif(String atRule) throws CSSException {
      List<CssNode> nodes = currentParent.peek().getNodes();
      CssIf lastIf = findLastIfInChain(nodes);

      if (lastIf == null) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "@elif must immediately follow an @if or @elif", null);
      }

      assert lastIf.getElseNodes().isEmpty();

      // @elif -> lif (because parseIf strips the first three chars)
      parseIf(atRule.substring(2));

      // Fix up the structure by remove the newly-created node from the parent
      // context and moving it to the end of the @if chain
      lastIf.getElseNodes().add(nodes.remove(nodes.size() - 1));
    }

    /**
     * The else nodes are processed as though they were written as {@code @elif
     * true} rules.
     */
    void parseElse(String atRule) throws CSSException {
      // The last CssIf in the if/else chain
      CssIf lastIf = findLastIfInChain(currentParent.peek().getNodes());

      if (lastIf == null) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "@else must immediately follow an @if or @elif", null);
      }

      // Create the CssIf to hold the @else rules
      String fakeElif = "@elif (true) " + atRule.substring(atRule.indexOf("{"));
      parseElif(fakeElif);
      CssIf elseIf = findLastIfInChain(currentParent.peek().getNodes());

      assert lastIf.getElseNodes().size() == 1
          && lastIf.getElseNodes().get(0) == elseIf;
      assert elseIf.getElseNodes().isEmpty();

      // Merge the rules into the last CssIf to break the chain and prevent
      // @else followed by @else
      lastIf.getElseNodes().clear();
      lastIf.getElseNodes().addAll(elseIf.getNodes());
    }

    void parseEval(String atRule) throws CSSException {
      // @eval key com.google.Type.staticFunction
      String[] parts = atRule.substring(0, atRule.length() - 1).split("\\s");

      if (parts.length != 3) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "Incorrect number of parts for @eval", null);
      }

      CssEval eval = new CssEval(parts[1], parts[2]);
      addNode(eval);
    }

    void parseExternal(String atRule) throws CSSException {
      // @external .foo, bar; Drop the dots and commas
      String[] parts = atRule.substring(10, atRule.length() - 1).replaceAll(
          "(, *)|( +)", " ").replaceAll("\\.", "").split(" ");

      CssExternalSelectors externals = new CssExternalSelectors();
      Collections.addAll(externals.getClasses(), parts);
      addNode(externals);
    }

    void parseIf(String atRule) throws CSSException {
      String predicate = atRule.substring(3, atRule.indexOf('{') - 1).trim();
      String blockContents = atRule.substring(atRule.indexOf('{') + 1,
          atRule.length() - 1);

      CssIf cssIf = new CssIf();

      if (predicate.startsWith("(") && predicate.endsWith(")")) {
        cssIf.setExpression(predicate);
      } else {

        String[] predicateParts = predicate.split("\\s");

        switch (predicateParts.length) {
          case 0:
            throw new CSSException(CSSException.SAC_SYNTAX_ERR,
                "Incorrect format for @if predicate", null);
          case 1:
            if (predicateParts[0].length() == 0) {
              throw new CSSException(CSSException.SAC_SYNTAX_ERR,
                  "Incorrect format for @if predicate", null);
            }
            errors.log(
                TreeLogger.WARN,
                "Deprecated syntax for Java expression detected. Enclose the expression in parentheses");
            cssIf.setExpression(predicateParts[0]);
            break;
          default:
            if (predicateParts[0].startsWith("!")) {
              cssIf.setNegated(true);
              cssIf.setProperty(predicateParts[0].substring(1));
            } else {
              cssIf.setProperty(predicateParts[0]);
            }
            String[] values = new String[predicateParts.length - 1];
            System.arraycopy(predicateParts, 1, values, 0, values.length);
            cssIf.setPropertyValues(values);
        }
      }

      parseInnerStylesheet("@if", cssIf, blockContents);
    }

    void parseNoflip(String atRule) throws CSSException {
      String blockContents = atRule.substring(atRule.indexOf('{') + 1,
          atRule.length() - 1);

      parseInnerStylesheet("@noflip", new CssNoFlip(), blockContents);
    }

    void parseSprite(String atRule) throws CSSException {
      CssSprite sprite = new CssSprite();
      currentRule = sprite;
      addNode(sprite);

      // Flag to tell startSelector() to use the CssSprite instead of creating
      // its own CssRule.
      nextSelectorCreatesRule = false;

      // parse the inner text
      InputSource s = new InputSource();
      s.setCharacterStream(new StringReader(atRule.substring(7)));
      Parser parser = new Parser();
      parser.setDocumentHandler(this);
      parser.setErrorHandler(errors);

      try {
        parser.parseRule(s);
      } catch (IOException e) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "Unable to parse @sprite", e);
      }
    }

    void parseUrl(String atRule) throws CSSException {
      // @url key dataResourceFunction
      String[] parts = atRule.substring(0, atRule.length() - 1).split("\\s");

      if (parts.length != 3) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "Incorrect number of parts for @url", null);
      }

      CssUrl url = new CssUrl(parts[1], parts[2]);
      addNode(url);
    }

    /**
     * Add a node to the current parent.
     */
    private void addNode(CssNode node) {
      currentParent.peek().getNodes().add(node);
    }

    private <T extends CssNode & HasNodes> void parseInnerStylesheet(
        String tagName, T parent, String blockContents) {
      pushParent(parent);

      // parse the inner text
      InputSource s = new InputSource();
      s.setCharacterStream(new StringReader(blockContents));
      Parser parser = new Parser();
      parser.setDocumentHandler(this);
      parser.setErrorHandler(errors);

      try {
        parser.parseStyleSheet(s);
      } catch (IOException e) {
        throw new CSSException(CSSException.SAC_SYNTAX_ERR, "Unable to parse "
            + tagName, e);
      }

      if (currentParent.pop() != parent) {
        // This is a coding error
        throw new RuntimeException("Incorrect element popped");
      }
    }

    /**
     * Adds a node to the current parent and then makes the node the current
     * parent node.
     */
    private <T extends CssNode & HasNodes> void pushParent(T newParent) {
      addNode(newParent);
      currentParent.push(newParent);
    }
  }

  /**
   * Extracts all properties in a document into a List.
   */
  private static class PropertyExtractor implements DocumentHandler {
    private final List<Value> values;

    private PropertyExtractor(List<Value> values) {
      this.values = values;
    }

    public void comment(String text) throws CSSException {
    }

    public void endDocument(InputSource source) throws CSSException {
    }

    public void endFontFace() throws CSSException {
    }

    public void endMedia(SACMediaList media) throws CSSException {
    }

    public void endPage(String name, String pseudoPage) throws CSSException {
    }

    public void endSelector(SelectorList selectors) throws CSSException {
    }

    public void ignorableAtRule(String atRule) throws CSSException {
    }

    public void importStyle(String uri, SACMediaList media,
        String defaultNamespaceURI) throws CSSException {
    }

    public void namespaceDeclaration(String prefix, String uri)
        throws CSSException {
    }

    public void property(String name, LexicalUnit value, boolean important)
        throws CSSException {
      extractValueOf(values, value);
    }

    public void startDocument(InputSource source) throws CSSException {
    }

    public void startFontFace() throws CSSException {
    }

    public void startMedia(SACMediaList media) throws CSSException {
    }

    public void startPage(String name, String pseudoPage) throws CSSException {
    }

    public void startSelector(SelectorList selectors) throws CSSException {
    }
  }

  /**
   * Associates a template CssStylesheet with a timestamp.
   */
  private static class CachedStylesheet {
    private final CssStylesheet sheet;
    private final long timestamp;

    public CachedStylesheet(CssStylesheet sheet, long timestamp) {
      this.sheet = sheet;
      this.timestamp = timestamp;
    }

    public CssStylesheet getCopyOfStylesheet() {
      return new CssStylesheet(sheet);
    }

    public long getTimestamp() {
      return timestamp;
    }
  }

  private static final String LITERAL_FUNCTION_NAME = "literal";
  /**
   * We cache the stylesheets to prevent repeated parsing of the same source
   * material. This is a common case if the user is using UiBinder's implicit
   * stylesheets. It is necessary to use the list of URLs passed to exec because
   * of the eager variable expansion performed by
   * {@link GenerationHandler#parseDef(String)}.
   */
  private static final Map<List<URL>, SoftReference<CachedStylesheet>> SHEETS = Collections.synchronizedMap(new HashMap<List<URL>, SoftReference<CachedStylesheet>>());
  private static final String VALUE_FUNCTION_NAME = "value";

  /**
   * Create a CssStylesheet from the contents of one or more URLs. If multiple
   * URLs are provided, the generated stylesheet will be created as though the
   * contents of the URLs had been concatenated.
   */
  public static CssStylesheet exec(TreeLogger logger, URL... stylesheets)
      throws UnableToCompleteException {

    long mtime = ResourceGeneratorUtil.getLastModified(stylesheets, logger);

    List<URL> sheets = Arrays.asList(stylesheets);
    SoftReference<CachedStylesheet> ref = SHEETS.get(sheets);
    CachedStylesheet toReturn = ref == null ? null : ref.get();
    if (toReturn != null) {
      if (mtime != 0 && mtime <= toReturn.getTimestamp()) {
        logger.log(TreeLogger.DEBUG, "Using cached result");
        return toReturn.getCopyOfStylesheet();
      } else {
        logger.log(TreeLogger.DEBUG, "Invalidating cached stylesheet");
      }
    }

    Parser p = new Parser();
    Errors errors = new Errors(logger);
    GenerationHandler g = new GenerationHandler(errors);
    p.setDocumentHandler(g);
    p.setErrorHandler(errors);

    for (URL stylesheet : sheets) {
      TreeLogger branchLogger = logger.branch(TreeLogger.DEBUG,
          "Parsing CSS stylesheet " + stylesheet.toExternalForm());
      try {
        p.parseStyleSheet(stylesheet.toURI().toString());
        continue;
      } catch (CSSException e) {
        branchLogger.log(TreeLogger.ERROR, "Unable to parse CSS", e);
      } catch (IOException e) {
        branchLogger.log(TreeLogger.ERROR, "Unable to parse CSS", e);
      } catch (URISyntaxException e) {
        branchLogger.log(TreeLogger.ERROR, "Unable to parse CSS", e);
      }
      throw new UnableToCompleteException();
    }

    if (errors.fatalErrorEncountered) {
      // Logging will have been performed by the Errors instance, just exit
      throw new UnableToCompleteException();
    }

    toReturn = new CachedStylesheet(g.css, mtime);
    SHEETS.put(new ArrayList<URL>(sheets), new SoftReference<CachedStylesheet>(
        toReturn));
    return toReturn.getCopyOfStylesheet();
  }

  /**
   * Expresses an rgb function as a hex expression.
   *
   * @param colors a sequence of LexicalUnits, assumed to be
   *          <code>(VAL COMMA VAL COMMA VAL)</code> where VAL can be an INT or
   *          a PERCENT (which is then converted to INT)
   * @return the minimal hex expression for the RGB color values
   */
  private static Value colorValue(LexicalUnit colors) {
    LexicalUnit red = colors;
    int r = getRgbComponentValue(red);
    LexicalUnit green = red.getNextLexicalUnit().getNextLexicalUnit();
    int g = getRgbComponentValue(green);
    LexicalUnit blue = green.getNextLexicalUnit().getNextLexicalUnit();
    int b = getRgbComponentValue(blue);

    String sr = Integer.toHexString(r);
    if (sr.length() == 1) {
      sr = "0" + sr;
    }

    String sg = Integer.toHexString(g);
    if (sg.length() == 1) {
      sg = "0" + sg;
    }

    String sb = Integer.toHexString(b);
    if (sb.length() == 1) {
      sb = "0" + sb;
    }

    // #AABBCC --> #ABC
    if (sr.charAt(0) == sr.charAt(1) && sg.charAt(0) == sg.charAt(1)
        && sb.charAt(0) == sb.charAt(1)) {
      sr = sr.substring(1);
      sg = sg.substring(1);
      sb = sb.substring(1);
    }

    return new IdentValue("#" + sr + sg + sb);
  }

  private static String escapeIdent(String selector) {
    assert selector.length() > 0;

    StringBuilder toReturn = new StringBuilder();

    if (selector.charAt(0) == '-') {
      // Allow leading hyphen
      selector = selector.substring(1);
      toReturn.append('-');
    }

    if (!isIdentStart(selector.charAt(0))) {
      toReturn.append('\\');
    }
    toReturn.append(selector.charAt(0));

    if (selector.length() > 1) {
      for (char c : selector.substring(1).toCharArray()) {
        if (!isIdentPart(c)) {
          toReturn.append('\\');
        }
        toReturn.append(c);
      }
    }
    return toReturn.toString();
  }

  /**
   * Convert a LexicalUnit list into a List of Values.
   */
  private static void extractValueOf(List<Value> accumulator, LexicalUnit value) {
    do {
      accumulator.add(valueOf(value));
      value = value.getNextLexicalUnit();
    } while (value != null);
  }

  /**
   * The elif and else constructs are modeled as nested if statements in the
   * CssIf's elseNodes field. This method will search a list of CssNodes and
   * remove the last chained CssIf from the last element in the list of nodes.
   */
  private static CssIf findLastIfInChain(List<CssNode> nodes) {
    if (nodes.isEmpty()) {
      return null;
    }

    CssNode lastNode = nodes.get(nodes.size() - 1);
    if (lastNode instanceof CssIf) {
      CssIf asIf = (CssIf) lastNode;
      if (asIf.getElseNodes().isEmpty()) {
        return asIf;
      } else {
        return findLastIfInChain(asIf.getElseNodes());
      }
    }
    return null;
  }

  /**
   * Return an integer value from 0-255 for a component of an RGB color.
   *
   * @param color typed value from the CSS parser, which may be an INTEGER or a
   *          PERCENTAGE
   * @return integer value from 0-255
   * @throws IllegalArgumentException if the color is not an INTEGER or
   *           PERCENTAGE value
   */
  private static int getRgbComponentValue(LexicalUnit color) {
    switch (color.getLexicalUnitType()) {
      case LexicalUnit.SAC_INTEGER:
        return Math.min(color.getIntegerValue(), 255);
      case LexicalUnit.SAC_PERCENTAGE:
        return (int) Math.min(color.getFloatValue() * 255, 255);
      default:
        throw new CSSException(CSSException.SAC_SYNTAX_ERR,
            "RGB component value must be integer or percentage, was " + color,
            null);
    }
  }

  private static boolean isIdentPart(char c) {
    return Character.isLetterOrDigit(c) || (c == '\\') || (c == '-')
        || (c == '_');
  }

  private static boolean isIdentStart(char c) {
    return Character.isLetter(c) || (c == '\\') || (c == '_');
  }

  /**
   * Utility method to concatenate strings.
   */
  private static String join(Iterable<Value> elements, String separator) {
    StringBuilder b = new StringBuilder();
    for (Iterator<Value> i = elements.iterator(); i.hasNext();) {
      b.append(i.next().toCss());
      if (i.hasNext()) {
        b.append(separator);
      }
    }
    return b.toString();
  }

  private static String maybeUnquote(String s) {
    if (s.startsWith("\"") && s.endsWith("\"")) {
      return s.substring(1, s.length() - 1);
    }
    return s;
  }

  /**
   * Used when evaluating literal() rules.
   */
  private static String unescapeLiteral(String s) {
    s = s.replaceAll(Pattern.quote("\\\""), "\"");
    s = s.replaceAll(Pattern.quote("\\\\"), Matcher.quoteReplacement("\\"));
    return s;
  }

  private static String valueOf(Condition condition) {
    if (condition instanceof AttributeCondition) {
      AttributeCondition c = (AttributeCondition) condition;
      switch (c.getConditionType()) {
        case Condition.SAC_ATTRIBUTE_CONDITION:
          return "[" + c.getLocalName()
              + (c.getValue() != null ? "=\"" + c.getValue() + '"' : "") + "]";
        case Condition.SAC_ONE_OF_ATTRIBUTE_CONDITION:
          return "[" + c.getLocalName() + "~=\"" + c.getValue() + "\"]";
        case Condition.SAC_BEGIN_HYPHEN_ATTRIBUTE_CONDITION:
          return "[" + c.getLocalName() + "|=\"" + c.getValue() + "\"]";
        case Condition.SAC_ID_CONDITION:
          return "#" + c.getValue();
        case Condition.SAC_CLASS_CONDITION:
          return "." + c.getValue();
        case Condition.SAC_PSEUDO_CLASS_CONDITION:
          return ":" + c.getValue();
      }

    } else if (condition instanceof CombinatorCondition) {
      CombinatorCondition c = (CombinatorCondition) condition;
      switch (condition.getConditionType()) {
        case Condition.SAC_AND_CONDITION:
          return valueOf(c.getFirstCondition())
              + valueOf(c.getSecondCondition());
        case Condition.SAC_OR_CONDITION:
          // Unimplemented in CSS2?
      }

    } else if (condition instanceof ContentCondition) {
      // Unimplemented in CSS2?

    } else if (condition instanceof LangCondition) {
      LangCondition c = (LangCondition) condition;
      return ":lang(" + c.getLang() + ")";

    } else if (condition instanceof NegativeCondition) {
      // Unimplemented in CSS2?
    } else if (condition instanceof PositionalCondition) {
      // Unimplemented in CSS2?
    }

    throw new RuntimeException("Unhandled condition of type "
        + condition.getConditionType() + " " + condition.getClass().getName());
  }

  private static Value valueOf(LexicalUnit value) {
    switch (value.getLexicalUnitType()) {
      case LexicalUnit.SAC_ATTR:
        return new IdentValue("attr(" + value.getStringValue() + ")");
      case LexicalUnit.SAC_IDENT:
        return new IdentValue(escapeIdent(value.getStringValue()));
      case LexicalUnit.SAC_STRING_VALUE:
        return new StringValue(value.getStringValue());
      case LexicalUnit.SAC_RGBCOLOR:
        // flute models the commas as operators so no separator needed
        return colorValue(value.getParameters());
      case LexicalUnit.SAC_INTEGER:
        return new NumberValue(value.getIntegerValue());
      case LexicalUnit.SAC_REAL:
        return new NumberValue(value.getFloatValue());
      case LexicalUnit.SAC_CENTIMETER:
      case LexicalUnit.SAC_DEGREE:
      case LexicalUnit.SAC_DIMENSION:
      case LexicalUnit.SAC_EM:
      case LexicalUnit.SAC_EX:
      case LexicalUnit.SAC_GRADIAN:
      case LexicalUnit.SAC_HERTZ:
      case LexicalUnit.SAC_KILOHERTZ:
      case LexicalUnit.SAC_MILLIMETER:
      case LexicalUnit.SAC_MILLISECOND:
      case LexicalUnit.SAC_PERCENTAGE:
      case LexicalUnit.SAC_PICA:
      case LexicalUnit.SAC_PIXEL:
      case LexicalUnit.SAC_POINT:
      case LexicalUnit.SAC_RADIAN:
      case LexicalUnit.SAC_SECOND:
        return new NumberValue(value.getFloatValue(),
            value.getDimensionUnitText());
      case LexicalUnit.SAC_URI:
        return new IdentValue("url(" + value.getStringValue() + ")");
      case LexicalUnit.SAC_OPERATOR_COMMA:
        return new TokenValue(",");
      case LexicalUnit.SAC_COUNTER_FUNCTION:
      case LexicalUnit.SAC_COUNTERS_FUNCTION:
      case LexicalUnit.SAC_FUNCTION: {
        if (value.getFunctionName().equals(VALUE_FUNCTION_NAME)) {
          // This is a call to value()
          List<Value> params = new ArrayList<Value>();
          extractValueOf(params, value.getParameters());

          if (params.size() != 1 && params.size() != 3) {
            throw new CSSException(CSSException.SAC_SYNTAX_ERR,
                "Incorrect number of parameters to " + VALUE_FUNCTION_NAME,
                null);
          }

          Value dotPathValue = params.get(0);
          String dotPath = maybeUnquote(((StringValue) dotPathValue).getValue());
          String suffix = params.size() == 3
              ? maybeUnquote(((StringValue) params.get(2)).getValue()) : "";

          return new DotPathValue(dotPath, suffix);
        } else if (value.getFunctionName().equals(LITERAL_FUNCTION_NAME)) {
          // This is a call to value()
          List<Value> params = new ArrayList<Value>();
          extractValueOf(params, value.getParameters());

          if (params.size() != 1) {
            throw new CSSException(CSSException.SAC_SYNTAX_ERR,
                "Incorrect number of parameters to " + LITERAL_FUNCTION_NAME,
                null);
          }

          Value expression = params.get(0);
          if (!(expression instanceof StringValue)) {
            throw new CSSException(CSSException.SAC_SYNTAX_ERR,
                "The single argument to " + LITERAL_FUNCTION_NAME
                    + " must be a string value", null);
          }

          String s = maybeUnquote(((StringValue) expression).getValue());
          s = unescapeLiteral(s);

          return new IdentValue(s);

        } else {
          List<Value> parameters = new ArrayList<Value>();
          extractValueOf(parameters, value.getParameters());
          return new FunctionValue(value.getFunctionName(),
              new ListValue(parameters));
        }
      }
      case LexicalUnit.SAC_INHERIT:
        return new IdentValue("inherit");
      case LexicalUnit.SAC_OPERATOR_EXP:
        return new TokenValue("^");
      case LexicalUnit.SAC_OPERATOR_GE:
        return new TokenValue(">=");
      case LexicalUnit.SAC_OPERATOR_GT:
        return new TokenValue(">");
      case LexicalUnit.SAC_OPERATOR_LE:
        return new TokenValue("<=");
      case LexicalUnit.SAC_OPERATOR_LT:
        return new TokenValue("<");
      case LexicalUnit.SAC_OPERATOR_MINUS:
        return new TokenValue("-");
      case LexicalUnit.SAC_OPERATOR_MOD:
        return new TokenValue("%");
      case LexicalUnit.SAC_OPERATOR_MULTIPLY:
        return new TokenValue("*");
      case LexicalUnit.SAC_OPERATOR_PLUS:
        return new TokenValue("+");
      case LexicalUnit.SAC_OPERATOR_SLASH:
        return new TokenValue("/");
      case LexicalUnit.SAC_OPERATOR_TILDE:
        return new IdentValue("~");
      case LexicalUnit.SAC_RECT_FUNCTION: {
        // Just return this as a String
        List<Value> parameters = new ArrayList<Value>();
        extractValueOf(parameters, value.getParameters());
        return new IdentValue("rect(" + join(parameters, "") + ")");
      }
      case LexicalUnit.SAC_SUB_EXPRESSION:
        // Should have been taken care of by our own traversal
      case LexicalUnit.SAC_UNICODERANGE:
        // Cannot be expressed in CSS2
    }
    throw new RuntimeException("Unhandled LexicalUnit type "
        + value.getLexicalUnitType());
  }

  private static String valueOf(Selector selector) {
    if (selector instanceof CharacterDataSelector) {
      // Unimplemented in CSS2?

    } else if (selector instanceof ConditionalSelector) {
      ConditionalSelector s = (ConditionalSelector) selector;
      String simpleSelector = valueOf(s.getSimpleSelector());

      if ("*".equals(simpleSelector)) {
        // Don't need the extra * for compound selectors
        return valueOf(s.getCondition());
      } else {
        return simpleSelector + valueOf(s.getCondition());
      }

    } else if (selector instanceof DescendantSelector) {
      DescendantSelector s = (DescendantSelector) selector;
      switch (s.getSelectorType()) {
        case Selector.SAC_CHILD_SELECTOR:
          if (s.getSimpleSelector().getSelectorType() == Selector.SAC_PSEUDO_ELEMENT_SELECTOR) {
            return valueOf(s.getAncestorSelector()) + ":"
                + valueOf(s.getSimpleSelector());
          } else {
            return valueOf(s.getAncestorSelector()) + ">"
                + valueOf(s.getSimpleSelector());
          }
        case Selector.SAC_DESCENDANT_SELECTOR:
          return valueOf(s.getAncestorSelector()) + " "
              + valueOf(s.getSimpleSelector());
      }

    } else if (selector instanceof ElementSelector) {
      ElementSelector s = (ElementSelector) selector;
      if (s.getLocalName() == null) {
        return "*";
      } else {
        return escapeIdent(s.getLocalName());
      }

    } else if (selector instanceof NegativeSelector) {
      // Unimplemented in CSS2?

    } else if (selector instanceof ProcessingInstructionSelector) {
      // Unimplemented in CSS2?

    } else if (selector instanceof SiblingSelector) {
      SiblingSelector s = (SiblingSelector) selector;
      return valueOf(s.getSelector()) + "+" + valueOf(s.getSiblingSelector());
    }

    throw new RuntimeException("Unhandled selector of type "
        + selector.getClass().getName());
  }

  /**
   * Utility class.
   */
  private GenerateCssAst() {
  }
}
