/*
 * Copyright 2009 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.rg;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.resources.css.GenerateCssAst;
import com.google.gwt.resources.css.ast.CssNode;
import com.google.gwt.resources.css.ast.CssStylesheet;
import com.google.gwt.resources.css.ast.CssVisitor;
import com.google.gwt.resources.css.ast.HasNodes;
import com.google.gwt.resources.ext.ResourceContext;

import junit.framework.TestCase;

import java.net.URL;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

/**
 * Contains functions for golden-output tests that are concerned with structural
 * modifications to the CSS AST.
 */
public class CssTestCase extends TestCase {
  /*
   * NB: This class is in the resources.rg package so that it can access
   * package-protected methods in CssResourceGenerator.
   */

  /**
   * Triggers an assertion if a CssNode is traversed more than once.
   * 
   * @see CssTestCase#assertNoAliasing(CssNode)
   */
  public static class AliasDetector extends CssVisitor {
    private final Map<CssNode, Void> seen = new IdentityHashMap<CssNode, Void>();

    @Override
    protected void doAccept(List<? extends CssNode> list) {
      for (CssNode node : list) {
        doAccept(node);
      }
    }

    @Override
    protected <T extends CssNode> T doAccept(T node) {
      assertFalse("Found repeated node " + node.toString(),
          seen.containsKey(node));
      seen.put(node, null);
      return super.doAccept(node);
    }

    @Override
    protected void doAcceptWithInsertRemove(List<? extends CssNode> list) {
      for (CssNode node : list) {
        doAccept(node);
      }
    }
  }

  /**
   * Total fake, no implementations.
   */
  private static class FakeContext implements ResourceContext {
    public String deploy(String suggestedFileName, String mimeType,
        byte[] data, boolean forceExternal) throws UnableToCompleteException {
      return null;
    }

    @Deprecated
    public String deploy(URL resource, boolean forceExternal)
        throws UnableToCompleteException {
      return null;
    }

    public String deploy(URL resource, String mimeType, boolean forceExternal)
        throws UnableToCompleteException {
      return null;
    }

    public <T> T getCachedData(String key, Class<T> clazz) {
      return null;
    }

    public JClassType getClientBundleType() {
      return null;
    }

    public GeneratorContext getGeneratorContext() {
      return null;
    }

    public String getImplementationSimpleSourceName()
        throws IllegalStateException {
      return null;
    }

    public <T> boolean putCachedData(String key, T value) {
      return false;
    }

    public boolean supportsDataUrls() {
      return true;
    }
  }

  /**
   * Asserts that two CssNodes are identical.
   */
  protected static <T extends CssNode & HasNodes> void assertEquals(
      TreeLogger logger, T expected, T test) throws UnableToCompleteException {
    String expectedCss = CssResourceGenerator.makeExpression(logger,
        new FakeContext(), null, expected, false);
    String testCss = CssResourceGenerator.makeExpression(logger,
        new FakeContext(), null, test, false);
    assertEquals(expectedCss, testCss);
  }

  /**
   * Ensure that no CssNode is traversed more than once due to AST errors.
   */
  protected static void assertNoAliasing(CssNode node) {
    (new AliasDetector()).accept(node);
  }

  /**
   * Compares the generated Java expressions for an input file, transformed in
   * order by the specified visitors, and a golden-output file.
   */
  private static void test(TreeLogger logger, URL test, URL expected,
      CssVisitor... visitors) throws UnableToCompleteException {

    CssStylesheet expectedSheet = null;
    CssStylesheet testSheet = null;

    try {
      expectedSheet = GenerateCssAst.exec(logger, expected);
      testSheet = GenerateCssAst.exec(logger, test);
    } catch (UnableToCompleteException e) {
      fail("Unable to parse stylesheet");
    }

    for (CssVisitor v : visitors) {
      v.accept(testSheet);
    }

    assertEquals(logger, expectedSheet, testSheet);
  }

  /**
   * Runs a test.
   * 
   * @param testName is used to compute the test and expected resource paths.
   * @param reversible if <code>true</code>, the test will attempt to transform
   *          the expected css into the test css
   */
  protected void test(TreeLogger logger, String testName, boolean reversible,
      CssVisitor... visitors) throws UnableToCompleteException {
    String packagePath = getClass().getPackage().getName().replace('.', '/')
        + "/";
    URL testUrl = getClass().getClassLoader().getResource(
        packagePath + testName + "_test.css");
    assertNotNull("Could not find testUrl", testUrl);
    URL expectedUrl = getClass().getClassLoader().getResource(
        packagePath + testName + "_expected.css");
    assertNotNull("Could not find testUrl", expectedUrl);

    test(logger, testUrl, expectedUrl, visitors);

    if (reversible) {
      test(logger, expectedUrl, testUrl, visitors);
    }
  }
}
