/**
 *
 */
package brn.gui.views;

import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Vector;

import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.PropertyDescriptor;

/**
 * @author kurth
 *
 */
public class BeanPropertySource implements IPropertySource {

  protected Object bean;

  protected IPropertyDescriptor[] propertyDescriptors;

  private String[] ignoredProperties;

  public BeanPropertySource(Object bean) {
    this(bean, new String[] {});
  }

  public BeanPropertySource(Object bean, String[] ignoredProperties) {
    this.bean = bean;
    this.ignoredProperties = ignoredProperties;
  }

  protected BeanPropertySource() {
    this.bean = null;
  }

  protected boolean isPropertyIgnored(String name) {
    if (name.equals("class"))
      return true;
    for (int i = 0; i < ignoredProperties.length; i++) {
      if (ignoredProperties[i].equals(name))
        return true;
    }
    return false;
  }

  public void setBean(Object bean) {
    this.bean = bean;
    propertyDescriptors = null;
  }

  protected IPropertyDescriptor getPropertyDescriptor(Object id) {
    for (int i = 0; i < propertyDescriptors.length; i++) {
      if (!propertyDescriptors[i].getId().equals(id))
        continue;

      return propertyDescriptors[i];
    }

    return null;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.views.properties.IPropertySource#getEditableValue()
   */
  public Object getEditableValue() {
    // TODO Auto-generated method stub
    return null;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
   */
  public IPropertyDescriptor[] getPropertyDescriptors() {
    if (null == bean)
      propertyDescriptors = new IPropertyDescriptor[0];

    if (null == propertyDescriptors) {
      try {
        BeanInfo info = Introspector.getBeanInfo(bean.getClass());
        BeanDescriptor descr = info.getBeanDescriptor();
        String category = descr.getName();

        java.beans.PropertyDescriptor[] props = info.getPropertyDescriptors();

        Vector<IPropertyDescriptor> descriptors = new Vector<IPropertyDescriptor>(props.length);
        for (int k = 0; k < props.length; k++) {
          String name = props[k].getDisplayName();
          if (isPropertyIgnored(name))
            continue;

          PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, name);
          propertyDescriptor.setCategory(category);
          descriptors.add(propertyDescriptor);
        }

        propertyDescriptors = descriptors.toArray(new IPropertyDescriptor[0]);
      } catch (IntrospectionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        propertyDescriptors = new IPropertyDescriptor[0];
      }
    }

    return propertyDescriptors;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
   */
  public Object getPropertyValue(Object id) {
    String ret = "error";
    try {
      BeanInfo info = Introspector.getBeanInfo(bean.getClass());
      java.beans.PropertyDescriptor[] props = info.getPropertyDescriptors();

      for (int k = 0; k < props.length; k++) {
        String name = props[k].getDisplayName();
        if (!name.equals(id))
          continue;

        java.beans.PropertyDescriptor prop = props[k];
        Method mRead = prop.getReadMethod();
        if (mRead != null && mRead.getParameterTypes().length == 0) {
          Object value = mRead.invoke(bean, (Object[])null);
          if (null == value)
            return "null";
          else if (value.getClass().isArray()) {
            ArrayPropertySource source = new ArrayPropertySource(value);
//            ((PropertyDescriptor)getPropertyDescriptor(id)).setLabelProvider(source.getLabelProvider());
            return source;
          }
          else if (value instanceof Number
              ||value instanceof String
              ||value instanceof Boolean)
            ret = value.toString();
          else
            return new BeanPropertySource(value);
        }

        break;
      }
    } catch (IntrospectionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    return ret;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object)
   */
  public boolean isPropertySet(Object id) {
    // TODO Auto-generated method stub
    return false;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object)
   */
  public void resetPropertyValue(Object id) {
    // TODO Auto-generated method stub

  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
   */
  public void setPropertyValue(Object id, Object value) {
    // TODO Auto-generated method stub

  }

}
