/*
 * 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.beans.Beans;
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 DesignTimeUtilsImpl#isDesignTime(String)}.
   */
  public void test_isDesignTime_evaluate() throws Exception {
    // not design time
    {
      Beans.setDesignTime(false);
      assertEquals(false, DesignTimeUtilsImpl.isDesignTime("no.Matter"));
    }
    // not this Binder
    try {
      Beans.setDesignTime(true);
      System.setProperty("gwt.UiBinder.isDesignTime my.Binder", "true");
      assertEquals(false, DesignTimeUtilsImpl.isDesignTime("other.Binder"));
    } finally {
      Beans.setDesignTime(false);
      System.clearProperty("gwt.UiBinder.isDesignTime my.design.Binder");
    }
    // OK
    try {
      Beans.setDesignTime(true);
      System.setProperty("gwt.UiBinder.isDesignTime my.Binder", "true");
      assertEquals(true, DesignTimeUtilsImpl.isDesignTime("my.Binder"));
    } finally {
      Beans.setDesignTime(false);
      System.clearProperty("gwt.UiBinder.isDesignTime my.design.Binder");
    }
  }

  /**
   * 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#isDesignTime()}.
   */
  public void test_isDesignTime_default() throws Exception {
    assertEquals(false, stub.isDesignTime());
  }

  /**
   * Test for {@link DesignTimeUtils#isDesignTime()}.
   */
  public void test_getOwnerCheck_designTime() throws Exception {
    assertEquals(true, impl.isDesignTime());
  }

  /**
   * 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));
    }
  };
}
