/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * 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.intellij.util.xml;

import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.impl.DomTestCase;
import com.intellij.util.xml.ui.DomUIFactory;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @author peter
 */
public class DomSimpleValuesTest extends DomTestCase {

  private MyElement createElement(final String xml) throws IncorrectOperationException {
    return createElement(xml, MyElement.class);
  }

  public void testGetValue() throws Throwable {
    final String text = "<a>foo</a>";
    assertEquals("foo", createElement(text).getTagValue());
    assertEquals("foo", createElement(text).getValue());
  }

  public void testSetValue() throws Throwable {
    final MyElement element = createElement("<a/>");
    assertEquals("", element.getValue());
    element.setValue(239);
    assertEquals("239", element.getValue());
    assertEquals("239", element.getXmlTag().getValue().getText());
    myCallRegistry.putExpected(new DomEvent(element, false));

    myCallRegistry.assertResultsAndClear();
  }

  public void testDefineAndSet() throws Throwable {
    final MyElement element = getDomManager().getFileElement(createXmlFile(""), MyElement.class, "root").getRootElement();
    myCallRegistry.clear();
    assertNull(element.getXmlTag());
    element.setValue(42);
    assertNotNull(element.getXmlTag());
    assertEquals("42", element.getXmlTag().getValue().getText());
    final DomElement element1 = element;
    myCallRegistry.putExpected(new DomEvent(element1, true));
    myCallRegistry.putExpected(new DomEvent(element, false));

    element.setValue((Integer)null);
    assertNull(element.getXmlTag());
    assertEquals(null, element.getValue());

    myCallRegistry.putExpected(new DomEvent(element, false));
    myCallRegistry.assertResultsAndClear();
  }


  public void testSimpleConverters() throws Throwable {
    assertEquals(239, createElement("<a>239</a>").getInt());
    assertEquals(true, createElement("<a>true</a>").getBoolean());
    assertEquals("true", createElement("<a>true</a>").getBuffer().toString());

    try {
      createElement("<a>true</a>").getInt();
      fail();
    }
    catch (NullPointerException e) {
    }
    try {
      createElement("<a>42</a>").getBoolean();
      fail();
    }
    catch (NullPointerException e) {
    }
  }

  public void testComment() throws Throwable {
    assertEquals(239, createElement("<a>" +
                                    "  <!-- some comment-->" +
                                    "  239" +
                                    "  <!-- some another comment-->" +
                                    "</a>").getInt());
  }

  public void testPsiClassConverter() throws Throwable {
    final String className = Object.class.getName();
    final PsiClass objectClass = getJavaFacade().findClass(className, GlobalSearchScope.allScope(getProject()));
    assertEquals(objectClass, createElement("<a>" + className + "</a>").getPsiClass());

    assertNull(createElement("<a>abcdef</a>").getPsiClass());
  }

  public void testEnums() throws Throwable {
    final MyElement element = createElement("<a/>", MyElement.class);
    assertNull(element.getEnum());

    element.setEnum(DomTestCase.MyEnum.BAR);
    assertEquals(DomTestCase.MyEnum.BAR, element.getEnum());
    assertEquals(DomTestCase.MyEnum.BAR.getValue(), element.getXmlTag().getValue().getText());

    element.setEnum(null);
    assertNull(element.getEnum());
    assertNull(element.getXmlTag());

    element.setValue(239);
    assertNull(element.getEnum());
  }

  public void testAttributeValues() throws Throwable {
    final MyElement element = createElement("<a attra=\"foo\"/>");
    final GenericAttributeValue<String> attributeValue = element.getAttributeValue();
    assertEquals("attra", attributeValue.getXmlElementName());
    assertEquals("foo", attributeValue.getValue());

    final GenericAttributeValue<Integer> attr = element.getAttr();
    attr.setValue(239);
    assertEquals(239, (int)attr.getValue());
    assertEquals("239", element.getXmlTag().getAttributeValue("attr"));
    final DomElement element1 = attr;
    myCallRegistry.putExpected(new DomEvent(element1, true));
    myCallRegistry.assertResultsAndClear();

    attr.setValue(42);
    myCallRegistry.putExpected(new DomEvent(attr, false));
    myCallRegistry.assertResultsAndClear();

    attr.setValue(null);
    assertNull(attr.getValue());
    assertNull(element.getXmlTag().getAttributeValue("attr"));
    assertNull(element.getXmlTag().getAttribute("attr", ""));
    myCallRegistry.putExpected(new DomEvent(attr, false));
    myCallRegistry.assertResultsAndClear();

    assertEquals("some-attribute", element.getSomeAttribute().getXmlElementName());

    assertNull(createElement("<a attra\"attr\"/>").getAttributeValue().getStringValue());
    assertNull(createElement("<a attra\"\"/>").getAttributeValue().getStringValue());
    assertNull(createElement("<a attra\"/>").getAttributeValue().getStringValue());
  }

  public void testGenericValue() throws Throwable {
    final MyElement element = createElement("<a><generic-child>239</generic-child></a>");
    final GenericDomValue<Integer> integerChild = element.getGenericChild();
    assertEquals(239, (int)integerChild.getValue());
    assertEquals("239", integerChild.getStringValue());
    integerChild.setValue(42);
    assertEquals(42, (int)integerChild.getValue());
    assertEquals("42", integerChild.getStringValue());
  }

  public void testAnnotatedGenericValue() throws Throwable {
    final MyElement element = createElement("<a><buffer>239</buffer></a>");
    element.getGenericChild().getValue();
    final GenericDomValue<StringBuffer> genericChild2 = element.getGenericChild2();
    assertEquals("239", genericChild2.getValue().toString());
  }

  public void testSpecialCharacters() throws Throwable {
    final MyElement element = createElement("");
    element.setValue("<");
    assertEquals("<", element.getValue());
    assertEquals("<![CDATA[<]]>", element.getXmlTag().getValue().getText());

    element.getAttributeValue().setValue("<");
    assertEquals("<", element.getAttributeValue().getValue());
    assertEquals("\"&lt;\"", element.getXmlTag().getAttribute("attra", null).getValueElement().getText());
  }

  public void testIndicators() throws Throwable {
    final MyElement element = createElement("<a><indicator/></a>");
    final GenericDomValue<Boolean> indicator = element.getIndicator();
    assertTrue(indicator.getValue());

    indicator.setValue(false);
    assertFalse(indicator.getValue());
    assertNull(indicator.getStringValue());
    assertNull(indicator.getXmlTag());
    assertEquals(0, element.getXmlTag().getSubTags().length);
    putExpected(new DomEvent(indicator, false));
    assertResultsAndClear();

    indicator.setValue(true);
    assertTrue(indicator.getValue());
    assertEquals("", indicator.getStringValue());
    assertSame(indicator.getXmlTag(), element.getXmlTag().getSubTags()[0]);
    final DomElement element1 = indicator;
    putExpected(new DomEvent(element1, true));
    assertResultsAndClear();

    final XmlTag tag = element.getXmlTag();
    new WriteCommandAction(getProject()) {
      @Override
      protected void run(Result result) throws Throwable {
        tag.add(createTag("<indicator/>"));
        tag.add(createTag("<indicator/>"));
      }
    }.execute();

    assertTrue(element.isValid());
    assertTrue(element.getIndicator().getValue());
    element.getIndicator().setValue(false);
    assertFalse(element.getIndicator().getValue());
    assertEquals(0, element.getXmlTag().findSubTags("indicator").length);
  }

  public void testConcreteGenericValue() throws Throwable {
    final ConcreteGeneric generic = createElement("", ConcreteGeneric.class);
    generic.setValue("abc");
    assertEquals("abc", generic.getValue());

    DomUIFactory.SET_VALUE_METHOD.invoke(generic, "def");
    assertEquals("def", DomUIFactory.GET_VALUE_METHOD.invoke(generic));
  }

  public void testConcreteGenericValueWithMethods() throws Throwable {
    final ConcreteGenericWithMethods generic = createElement("", ConcreteGenericWithMethods.class);
    generic.setValue("abc");
    assertEquals("abc", generic.getValue());

    DomUIFactory.SET_VALUE_METHOD.invoke(generic, "def");
    assertEquals("def", DomUIFactory.GET_VALUE_METHOD.invoke(generic));
  }

  public void testNameValueInPresentation() throws Throwable {
    final MyElement element = createElement("");
    element.getAttr().setValue(23942);
    assertEquals("23942", element.getPresentation().getElementName());
  }

  public void testResolveToDomElement() throws Throwable {
    final RootInterface element = createElement("", RootInterface.class);
    final MyElement child1 = element.addChild();
    child1.getAttr().setValue(555);
    final MyElement child2 = element.addChild();
    child2.getAttr().setValue(777);

    final GenericDomValue<MyElement> resolve = child2.getResolve();
    resolve.setStringValue("777");
    assertEquals(child2, resolve.getValue());

    resolve.setValue(child1);
    assertEquals("555", resolve.getStringValue());
    assertEquals(child1, resolve.getValue());

    resolve.setStringValue("239");
    assertNull(resolve.getValue());

    final GenericDomValue<MyElement> resolve2 = child2.getResolve2();
    resolve2.setStringValue("777");
    assertEquals(child2, resolve2.getValue());
  }

  public void testPlainPsiTypeConverter() throws Throwable {
    assertNull(createElement("").getPsiType());
    assertSame(PsiType.INT, createElement("<a>int</a>").getPsiType());
    final PsiType psiType = createElement("<a>java.lang.String</a>").getPsiType();
    assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(psiType, PsiClassType.class).getCanonicalText());

    final PsiType arrayType = createElement("<a>int[]</a>").getPsiType();
    assertTrue(arrayType instanceof PsiArrayType);
    assertSame(PsiType.INT, ((PsiArrayType) arrayType).getComponentType());
  }

  public void testJvmPsiTypeConverter() throws Throwable {
    assertNull(createElement("").getJvmPsiType());
    assertNotNull(createElement("<a>int</a>").getJvmPsiType());
    final PsiClassType string = PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject()));
    final PsiType psiType = createElement("<a>java.lang.String</a>").getJvmPsiType();
    assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(psiType, PsiClassType.class).getCanonicalText());

    final PsiArrayType intArray = assertInstanceOf(createElement("<a>[I</a>").getJvmPsiType(), PsiArrayType.class);
    final PsiArrayType stringArray = assertInstanceOf(createElement("<a>[Ljava.lang.String;</a>").getJvmPsiType(), PsiArrayType.class);
    assertSame(PsiType.INT, intArray.getComponentType());
    assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(stringArray.getComponentType(), PsiClassType.class).getCanonicalText());

    assertJvmPsiTypeToString(intArray, "[I");
    assertJvmPsiTypeToString(stringArray, "[Ljava.lang.String;");
    assertJvmPsiTypeToString(string, "java.lang.String");
  }

  public void testValueCaching() throws Throwable {
    final GenericDomValue<String> element = createElement("<a><cached-value/></a>", MyElement.class).getCachedValue();
    assertEquals(0, ((MyConverter) element.getConverter()).fromStringCalls);
    assertEquals("", element.getValue());
    assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls);
    assertEquals("", element.getValue());
    assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls);
    element.setValue("1");
    assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls);
    assertEquals("1", element.getValue());
    assertEquals(2, ((MyConverter) element.getConverter()).fromStringCalls);
  }


  private void assertJvmPsiTypeToString(final PsiType type, final String expected) throws IncorrectOperationException {
    final MyElement element = createElement("");
    element.setJvmPsiType(type);
    assertEquals(expected, element.getValue());
  }

  public void testJavaStyledElement() throws IncorrectOperationException {
    JavaStyledElement element = createElement("<tag javaStyledAttribute=\"666\"></tag>", JavaStyledElement.class);
    assertEquals(element.getJavaStyledAttribute().getXmlElementName(), "javaStyledAttribute");
  }

  public void testGenericValueListConverter() throws Throwable {
    final MyElement element = createElement("<a><string-buffer>abc</string-buffer></a>");
    assertEquals("abc", element.getStringBuffers().get(0).getValue().toString());
  }

  public void testConvertAnnotationOnType() throws Throwable {
    final MyElement element =
      createElement("<a>" + "<my-generic-value>abc</my-generic-value>" + "<my-foo-generic-value>abc</my-foo-generic-value>" + "");
    assertEquals("bar", element.getMyGenericValue().getValue());
    assertEquals("foo", element.getMyFooGenericValue().getValue());
  }
  
  public void testEntities() throws Throwable {
    final MyElement element = createElement("<!DOCTYPE a SYSTEM \"aaa\"\n" +
                                            "[<!ENTITY idgenerator    \"identity\">]>\n" +
                                            "<a attra=\"a&lt;b\" some-attribute=\"&idgenerator;\">&xxx;+&idgenerator;+&amp;</a>");
    assertEquals("a<b", element.getAttributeValue().getValue());
    assertEquals("identity", element.getSomeAttribute().getValue());
//    assertEquals("&xxx;+identity+&", element.getValue());
  }

  public interface RootInterface extends DomElement {
    List<MyElement> getChildren();
    MyElement addChild();
  }


  public interface MyElement extends DomElement {
    @Attribute("attra")
    GenericAttributeValue<String> getAttributeValue();

    @NameValue
    GenericAttributeValue<Integer> getAttr();

    GenericAttributeValue<String> getSomeAttribute();

    String getValue();

    void setValue(Integer value);

    @TagValue()
    int getInt();

    void setValue(String value);

    @TagValue()
    boolean getBoolean();

    @TagValue()
    PsiType getPsiType();

    @Convert(JvmPsiTypeConverter.class)
    @TagValue()
    PsiType getJvmPsiType();

    @TagValue()
    @Convert(JvmPsiTypeConverter.class)
    void setJvmPsiType(PsiType psiType);

    @TagValue()
    DomTestCase.MyEnum getEnum();

    @TagValue
    void setEnum(DomTestCase.MyEnum value);

    @TagValue()
    @Convert(StringBufferConverter.class)
    StringBuffer getBuffer();

    @TagValue()
    PsiClass getPsiClass();

    @TagValue()
    String getTagValue();

    GenericDomValue<Integer> getGenericChild();

    @SubTag("buffer")
    @Convert(StringBufferConverter.class)
    GenericDomValue<StringBuffer> getGenericChild2();

    @SubTag(indicator = true)
    GenericDomValue<Boolean> getIndicator();

    @Resolve(MyElement.class)
    GenericDomValue<MyElement> getResolve();

    GenericDomValue<MyElement> getResolve2();

    @Convert(StringBufferConverter.class)
    List<GenericDomValue<StringBuffer>> getStringBuffers();

    @Convert(MyConverter.class) GenericDomValue<String> getCachedValue();

    MyGenericValue getMyGenericValue();

    @Convert(FooConverter.class)
    MyGenericValue getMyFooGenericValue();

  }

  @Convert(BarConverter.class)
  public interface MyGenericValue extends GenericDomValue<String> {
  }

  @NameStrategyForAttributes(JavaNameStrategy.class)
  public interface JavaStyledElement extends DomElement {
    GenericAttributeValue<String> getJavaStyledAttribute();
  }

  public interface ConcreteGeneric extends GenericDomValue<String> {
  }

  public interface ConcreteGenericWithMethods extends GenericDomValue<String> {
    @Override
    String getValue();

    @Override
    void setValue(String s);
  }

  public void testFuhrer() throws Throwable {
    final FieldGroup group = createElement("<field-group>\n" +
                                           "<group-name>myGroup</load-group-name>\n" +
                                           "<field-name>myField1</field-name>\n" +
                                           "<field-name>myField2</field-name>\n" +
                                           "</field-group>",
                                           FieldGroup.class);
    assertEquals(2, group.getFieldNames().size());
    assertEquals("myField1", group.getFieldNames().get(0).getValue().getName().getValue());
    assertEquals(null, group.getFieldNames().get(1).getValue());
  }

  public interface JavaeeModelElement {
  }

  public interface JavaeeDomModelElement extends JavaeeModelElement, DomElement {
}

  public interface FieldGroup extends JavaeeDomModelElement {

    GenericDomValue<String> getGroupName();

    List<GroupField> getFieldNames();

    GroupField addFieldName();
  }

  public interface GroupField extends JavaeeDomModelElement {

    @Convert(value = CmpFieldConverter.class)
    CmpField getValue();

    @Convert(value = CmpFieldConverter.class)
    void setValue(CmpField value);
  }

  public static class CmpFieldConverter extends ResolvingConverter<CmpField> {

    @Override
    public CmpField fromString(String s, ConvertContext context) {
      return ElementPresentationManager.findByName(getVariants(context), s);
    }

    @Override
    public String toString(CmpField t, ConvertContext context) {
      return t == null ? null : t.getName().getValue();
    }

    @Override
    @NotNull
    public Collection<CmpField> getVariants(ConvertContext context) {
      final DomElement element = context.getInvocationElement();
      return Arrays.asList(createCmpField(null, element), createCmpField("myField1", element), createCmpField("def", element));
    }

    private CmpField createCmpField(String name, DomElement element) {
      final CmpField mockElement = element.getManager().createMockElement(CmpField.class, element.getModule(), false);
      mockElement.getName().setValue(name);
      return mockElement;
    }
  }

  public interface CmpField extends JavaeeDomModelElement {
    @NameValue
    public GenericDomValue<String> getName();
  }

  public static class MyConverter extends Converter<String> {
    public int fromStringCalls = 0;

    @Override
    public String fromString(@Nullable @NonNls String s, final ConvertContext context) {
      fromStringCalls++;
      return s;
    }

    @Override
    public String toString(@Nullable String s, final ConvertContext context) {
      return s;
    }
  }

  public static class FooConverter extends Converter<String> {
    @Override
    public String fromString(@Nullable @NonNls final String s, final ConvertContext context) {
      return s == null ? null : "foo";
    }

    @Override
    public String toString(@Nullable final String s, final ConvertContext context) {
      return s;
    }
  }
  public static class BarConverter extends Converter<String> {
    @Override
    public String fromString(@Nullable @NonNls final String s, final ConvertContext context) {
      return s == null ? null : "bar";
    }

    @Override
    public String toString(@Nullable final String s, final ConvertContext context) {
      return s;
    }
  }

}
