package snow;

import java.awt.event.*;

import javax.swing.*;

import net.miginfocom.swing.MigLayout;

import org.junit.*;
import static org.junit.Assert.*;

import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.beans.Model;
import com.jgoodies.binding.beans.PropertyAdapter;
import com.jgoodies.binding.value.ValueModel;
import java.beans.*;
import java.io.*;
import snow.binding.*;

public class BindingTest {

    @Test
    public void testBinding() {
	final Bean bean = new Bean();
	ValueModel valueModel = new PropertyAdapter<Bean>(bean, Bean.PROPERTY, true);
	JFrame frame = new JFrame("test");
	frame.setLayout(new MigLayout());	
	JTextField field1 = new JTextField(20);
	frame.add(field1, "wrap");
	JTextField field2 = new JTextField(20);
	field2.setColumns(20);
	frame.add(field2, "wrap");
	JLabel field3 = new JLabel();
	frame.add(field3, "wrap");
	Bindings.bind(field1, valueModel, true);
	Bindings.bind(field2, valueModel, false);
	Bindings.bind(field3, "text", new PropertyAdapter<Bean>(bean, Bean.PROPERTY, true));
	JButton resetButton = new JButton("reset");
	resetButton.addActionListener(new ActionListener() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
		    bean.setProperty("cippalippa");
		}
		
	    });
	frame.add(resetButton);
	frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
	frame.pack();
	//frame.setVisible(true);
    }

    @Test
    public void testPropertyPath() {
	Bean bean = new Bean();
	bean.setBean(new Bean());
	bean.getBean().setProperty("ciao");
	ValueModel model = new BeanPropertyPathBinding(bean, "bean.property");
	final boolean[] flag = new boolean[] { true };
	model.addValueChangeListener(new PropertyChangeListener() {
		public void propertyChange(PropertyChangeEvent evt) {
		    System.out.println("change: " + evt);
		    flag[0] = false;
		}
	    });
	bean.getBean().setProperty("value2");
	if(flag[0]) {
	    fail("value was set but listener didn't fire");
	}
	flag[0] = true;
	bean.getBean().setProperty("value2");
	if(!flag[0]) {
	    fail("value was set to same value and listener fired");
	}
	model.setValue("42");
	assertEquals("42", bean.getBean().getProperty());
    }

    public static class BackingBean {
	private JButton button;
	public boolean buttonPressed = false;
	public void setButtonProperty(JButton b) {
	    button = b;
	}
	public JButton getButtonProperty() {
	    return button;
	}
	public void buttonAction(ActionEvent e) {
	    buttonPressed = true;
	}
    }

    @Test
    public void testBackingBean() {
	Snowlet s = Snow.getInterpretedSnowlet(new StringReader("(in-package :snow-user) (setq *debugger-hook* nil) (button :id button-property :on-action \"buttonAction\")"));
	BackingBean b = new BackingBean();
	s.setBackingBean(b);
	Object result = s.eval();
	assertEquals(result, b.getButtonProperty());
	b.getButtonProperty().doClick();
	assertTrue(b.buttonPressed);
    }
    
    public static void main(String[] args) {
	new BindingTest().testBinding();
    }
    
    public static class Bean extends Model {
	
	public static final String PROPERTY = "property";
	
	private String property = "cippalippa";
	private Bean bean;
	
	public String getProperty() {
	    System.out.println("get " + property);
	    return property;
	}
	
	public void setProperty(String property) {
	    String oldProperty = this.property;
	    this.property = property;
	    System.out.println("set " + property);
	    firePropertyChange(PROPERTY, oldProperty, property);
	}

	public Bean getBean() {
	    return bean;
	}
	
	public void setBean(Bean bean) {
	    this.bean = bean;
	}
	
    }
    
}
