/*
 * Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 */
package com.intellij.util.xmlb;

import com.intellij.openapi.util.text.StringUtilRt;
import com.intellij.util.xmlb.annotations.Property;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.*;
import java.util.List;

class AccessorBindingWrapper extends Binding implements MultiNodeBinding {
  protected final Binding myBinding;

  private final boolean myFlat;
  private final Property.Style beanStyle;

  public AccessorBindingWrapper(@NotNull MutableAccessor accessor,
                                @NotNull Binding binding,
                                boolean flat,
                                Property.Style beanStyle) {
    super(accessor);

    myBinding = binding;
    myFlat = flat;
    this.beanStyle = beanStyle;
  }

  public boolean isFlat() {
    return myFlat;
  }

  @Nullable
  @Override
  public Object serialize(@NotNull Object o, @Nullable Object context, @Nullable SerializationFilter filter) {
    Object value = myAccessor.read(o);
    if (value == null) {
      throw new XmlSerializationException("Property " + myAccessor + " of object " + o + " (" + o.getClass() + ") must not be null");
    }
    if (myFlat) {
      Element element = (Element)context;
      if (beanStyle == Property.Style.ATTRIBUTE && value instanceof Rectangle) {
        Rectangle bounds = (Rectangle)value;
        LOG.assertTrue(element != null);
        element.setAttribute("x", Integer.toString(bounds.x));
        element.setAttribute("y", Integer.toString(bounds.y));
        element.setAttribute("width", Integer.toString(bounds.width));
        element.setAttribute("height", Integer.toString(bounds.height));
      }
      else {
        ((BeanBinding)myBinding).serializeInto(value, element, filter);
      }
      return null;
    }
    else {
      return myBinding.serialize(value, context, filter);
    }
  }

  @Override
  public Object deserializeUnsafe(Object context, @NotNull Element element) {
    return deserialize(context, element);
  }

  @NotNull
  public Object deserialize(@NotNull Object context, @NotNull Element element) {
    Object currentValue = myAccessor.read(context);
    if (myBinding instanceof BeanBinding && myAccessor.isFinal()) {
      ((BeanBinding)myBinding).deserializeInto(currentValue, element);
    }
    else {
      Object deserializedValue;
      if (beanStyle == Property.Style.ATTRIBUTE && myBinding instanceof BeanBinding && ((BeanBinding)myBinding).myBeanClass == Rectangle.class) {
        int x = StringUtilRt.parseInt(element.getAttributeValue("x"), 0);
        int y = StringUtilRt.parseInt(element.getAttributeValue("y"), 0);
        int w = StringUtilRt.parseInt(element.getAttributeValue("width"), 0);
        int h = StringUtilRt.parseInt(element.getAttributeValue("height"), 0);
        deserializedValue = new Rectangle(x, y, w, h);
      }
      else {
        deserializedValue = myBinding.deserializeUnsafe(currentValue, element);
      }

      if (currentValue != deserializedValue) {
        myAccessor.set(context, deserializedValue);
      }
    }
    return context;
  }

  @Nullable
  @Override
  public Object deserializeList(@SuppressWarnings("NullableProblems") @NotNull Object context, @NotNull List<Element> elements) {
    Object currentValue = myAccessor.read(context);
    if (myBinding instanceof BeanBinding && myAccessor.isFinal()) {
      ((BeanBinding)myBinding).deserializeInto(currentValue, elements.get(0));
    }
    else {
      Object deserializedValue = Binding.deserializeList(myBinding, currentValue, elements);
      if (currentValue != deserializedValue) {
        myAccessor.set(context, deserializedValue);
      }
    }
    return context;
  }

  @Override
  public boolean isMulti() {
    return myBinding instanceof MultiNodeBinding && ((MultiNodeBinding)myBinding).isMulti();
  }

  @Override
  public boolean isBoundTo(@NotNull Element element) {
    return myBinding.isBoundTo(element);
  }
}

@@ -2675,38 +2675,72 @@
     
+Str
 in
-t
+g
  x
+A
  = 
-StringUtilRt.parseInt(
+element.getAttributeValue(%22x%22);%0A        String yA = 
 elem
@@ -2766,15 +2766,11 @@
 ue(%22
-x
+y
 %22)
-, 0)
 ;%0A  
@@ -2779,74 +2779,184 @@
     
-int y = StringUtilRt.parseInt(element.getAttributeValue(%22y%22), 0);%0A
+String wA = element.getAttributeValue(%22width%22);%0A        String hA = element.getAttributeValue(%22height%22);%0A%0A        if (xA != null && yA != null && wA != null && hA != null) %7B%0A  
     
@@ -2963,17 +2963,17 @@
     int 
-w
+x
  = Strin
@@ -2993,48 +2993,66 @@
 Int(
-element.getAttributeValue(%22width%22)
+xA, 0);%0A          int y = StringUtilRt.parseInt(yA
 , 0);%0A
+  
     
@@ -3089,49 +3089,66 @@
 Int(
-element.getAttributeValue(%22height%22)
+hA, 0);%0A          int w = StringUtilRt.parseInt(wA
 , 0);%0A
+  
     
@@ -3198,16 +3198,77 @@
  w, h);%0A
+        %7D%0A        else %7B%0A          return context;%0A        %7D%0A
       %7D%0A

fix WindowInfoTest — do not create Rectangle if no data