/*
 * Copyright 2010 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.uibinder.rebind;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.javac.impl.MockResourceOracle;

import junit.framework.TestCase;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Tests for {@link DesignTimeUtils}.
 */
public class DesignTimeUtilsTest extends TestCase {
  private static final W3cDomHelper docHelper = new W3cDomHelper(
      TreeLogger.NULL, new MockResourceOracle());
  private final DesignTimeUtils stub = DesignTimeUtilsStub.EMPTY;
  private final DesignTimeUtilsImpl impl = new DesignTimeUtilsImpl();

  /**
   * Test for {@link DesignTimeUtils#addDeclarations(IndentedWriter)}.
   */
  public void test_addDeclarations_default() throws Exception {
    String result = call_addDeclarations(stub);
    assertEquals("", result);
  }

  /**
   * Test for {@link DesignTimeUtils#addDeclarations(IndentedWriter)}.
   */
  public void test_addDeclarations_designTime() throws Exception {
    String result = call_addDeclarations(impl);
    assertContains(result, "public static interface DTObjectHandler");
    assertContains(result, "void handle(String path, Object object)");
    assertContains(result, "public DTObjectHandler dtObjectHandler;");
    assertContains(result,
        "public final java.util.Map dtAttributes = new java.util.HashMap();");
    assertContains(result,
        "private void dtPutAttribute(String key, Object...values) {");
  }

  private static String call_addDeclarations(DesignTimeUtils designTime) {
    StringWriter sw = new StringWriter();
    IndentedWriter indentedWriter = new IndentedWriter(new PrintWriter(sw));
    designTime.addDeclarations(indentedWriter);
    return sw.toString();
  }

  private static void assertContains(String content, String subString) {
    assertTrue(subString, content.contains(subString));
  }

  /**
   * Test for {@link DesignTimeUtils#getImplName(String)}.
   */
  public void test_getImplName_default() throws Exception {
    String basicName = "MyBinderImpl";
    String result = stub.getImplName(basicName);
    assertEquals(basicName, result);
  }

  /**
   * Test for {@link DesignTimeUtils#getImplName(String)}.
   */
  public void test_getImplName_designTime() throws Exception {
    String basicName = "MyBinderImpl";
    String result = impl.getImplName(basicName);
    // has "_designTime" substring
    String prefix = basicName + "_designTime";
    assertTrue(result.startsWith(prefix));
    // suffix is current time plus/minus 1 hour, so generates unique names
    long suffix = Long.parseLong(result.substring(prefix.length()));
    long delta = System.currentTimeMillis() - suffix;
    assertTrue(Math.abs(delta) < 1000 * 3600);
  }

  /**
   * Test for {@link DesignTimeUtils#getPath(Element)} and related methods.
   */
  public void test_path_default() throws Exception {
    Document doc = docHelper.documentFor("<root><first/><second/></root>", null);
    stub.rememberPathForElements(doc);
    Element first = getChildElement(doc.getDocumentElement(), "first");
    Element second = getChildElement(doc.getDocumentElement(), "second");
    assertEquals(null, stub.getPath(first));
    assertEquals(null, stub.getPath(second));
  }

  /**
   * Test for {@link DesignTimeUtils#getPath(Element)} and related methods.
   */
  public void test_path_designTime() throws Exception {
    Document doc = docHelper.documentFor(
        "<root><first/><second><subSecond/></second></root>", null);
    impl.rememberPathForElements(doc);
    Element first = getChildElement(doc.getDocumentElement(), "first");
    Element second = getChildElement(doc.getDocumentElement(), "second");
    Element subSecond = getChildElement(second, "subSecond");
    assertEquals("0/0", impl.getPath(first));
    assertEquals("0/1", impl.getPath(second));
    assertEquals("0/1/0", impl.getPath(subSecond));
  }

  /**
   * Test for {@link DesignTimeUtils#getTemplateContent(String)}.
   */
  public void test_getTemplateContent_default() throws Exception {
    String path = "the/path";
    assertEquals(null, stub.getTemplateContent(path));
  }

  /**
   * Test for {@link DesignTimeUtils#getTemplateContent(String)}.
   */
  public void test_getTemplateContent_designTime() throws Exception {
    String path = "the/path";
    String key = "gwt.UiBinder.designTime " + path;
    try {
      String content = "myContent";
      System.setProperty(key, content);
      assertEquals(content, impl.getTemplateContent(path));
    } finally {
      System.clearProperty(key);
    }
  }

  /**
   * Test for
   * {@link DesignTimeUtils#handleUIObject(IUiBinderWriterStatements, XMLElement, String)}
   * .
   */
  public void test_handleUIObject_default() throws Exception {
    WriterStatements writer = new WriterStatements();
    stub.handleUIObject(writer, null, "myField");
    assertEquals(0, writer.statements.size());
  }

  /**
   * Test for
   * {@link DesignTimeUtils#handleUIObject(IUiBinderWriterStatements, XMLElement, String)}
   * .
   */
  public void test_handleUIObject_designTime() throws Exception {
    // prepare XMLElement
    XMLElement element;
    {
      Document doc = docHelper.documentFor("<root><first/></root>", null);
      impl.rememberPathForElements(doc);
      Element first = getChildElement(doc.getDocumentElement(), "first");
      element = createXMLElement(first, impl);
    }
    // prepare statements
    List<String> statements;
    {
      WriterStatements writer = new WriterStatements();
      impl.handleUIObject(writer, element, "myField");
      statements = writer.statements;
    }
    // validate
    assertEquals(1, statements.size());
    assertEquals(
        "if (dtObjectHandler != null) dtObjectHandler.handle(\"0/0\", myField);",
        statements.get(0));
  }

  /**
   * Test for {@link DesignTimeUtils#putAttribute(XMLElement, String, String)}
   * and {@link DesignTimeUtils#writeAttributes(Statements)}.
   */
  public void test_putAttribute_default() throws Exception {
    List<String> statements = call_putAttribute(stub);
    // validate
    assertEquals(0, statements.size());
  }

  /**
   * Test for {@link DesignTimeUtils#putAttribute(XMLElement, String, String)}
   * and {@link DesignTimeUtils#writeAttributes(Statements)}.
   */
  public void test_putAttribute_designTime() throws Exception {
    List<String> statements = call_putAttribute(impl);
    // validate
    assertEquals(1, statements.size());
    assertEquals("dtPutAttribute(\"0/0 attr\", val);", statements.get(0));
  }

  private static List<String> call_putAttribute(DesignTimeUtils designTime)
      throws Exception {
    // prepare XMLElement
    XMLElement element;
    {
      Document doc = docHelper.documentFor("<root><first/></root>", null);
      designTime.rememberPathForElements(doc);
      Element first = getChildElement(doc.getDocumentElement(), "first");
      element = createXMLElement(first, designTime);
    }
    // prepare statements
    List<String> statements;
    {
      WriterStatements writer = new WriterStatements();
      designTime.putAttribute(element, "attr", "val");
      designTime.writeAttributes(writer);
      statements = writer.statements;
    }
    // done
    return statements;
  }

  /**
   * Test for {@link DesignTimeUtils#putAttribute(XMLElement, String, String[])}
   * .
   */
  public void test_putAttributeStrings_default() throws Exception {
    List<String> statements = call_putAttributeStrings(new String[]{"a", "b"},
        stub);
    // validate
    assertEquals(0, statements.size());
  }

  /**
   * Test for {@link DesignTimeUtils#putAttribute(XMLElement, String, String[])}
   * .
   */
  public void test_putAttributeStrings_designTime_empty() throws Exception {
    List<String> statements = call_putAttributeStrings(new String[]{}, impl);
    // validate
    assertEquals(0, statements.size());
  }

  /**
   * Test for {@link DesignTimeUtils#putAttribute(XMLElement, String, String[])}
   * .
   */
  public void test_putAttributeStrings_designTime() throws Exception {
    List<String> statements = call_putAttributeStrings(new String[]{"a", "b"},
        impl);
    // validate
    assertEquals(1, statements.size());
    assertEquals("dtPutAttribute(\"0/0 attr\", new String[] {a, b});",
        statements.get(0));
  }

  private static List<String> call_putAttributeStrings(String[] strings,
      DesignTimeUtils designTime) throws Exception {
    // prepare XMLElement
    XMLElement element;
    {
      Document doc = docHelper.documentFor("<root><first/></root>", null);
      designTime.rememberPathForElements(doc);
      Element first = getChildElement(doc.getDocumentElement(), "first");
      element = createXMLElement(first, designTime);
    }
    // prepare statements
    List<String> statements;
    {
      WriterStatements writer = new WriterStatements();
      designTime.putAttribute(element, "attr", strings);
      designTime.writeAttributes(writer);
      statements = writer.statements;
    }
    return statements;
  }

  /**
   * @return the only child {@link Element} with given tag name.
   */
  private static Element getChildElement(Element parent, String name) {
    NodeList elements = parent.getElementsByTagName(name);
    assertEquals(1, elements.getLength());
    return (Element) elements.item(0);
  }

  /**
   * @return the {@link XMLElement} wrapper for given {@link Element}.
   */
  private static XMLElement createXMLElement(Element elem,
      DesignTimeUtils designTime) {
    return new XMLElement(elem, null, null, null, null, designTime, null);
  }

  /**
   * Implementation of {@link IUiBinderWriterStatements} for simple statements.
   */
  static class WriterStatements extends Statements.Empty {
    List<String> statements = new ArrayList<String>();

    @Override
    public void addStatement(String format, Object... args) {
      statements.add(String.format(format, args));
    }
  };
}
