package leaf.ui;

import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;

import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.JTextComponent;

import com.evolute.utils.ui.text.CopyPasteHandler;

import leaf.data.Validator;

public class LeafTextAreaEditor extends JPanel
{

	public static final String ACTION_SAVE = "ACTION_SAVE";
	
	public static final String ACTION_REVERT = "ACTION_REVERT";
	
	private static final long serialVersionUID = 1L;

	private static final String ICON_NAME_SAVE = "leaf/ui/icons/save.png";
	
	private static final String ICON_NAME_REVERT = "leaf/ui/icons/revert.png";

	private final LeafButton buttonSave = LeafIconButton.createButton( ICON_NAME_SAVE );
	
	private final LeafButton buttonRevert = LeafIconButton.createButton( ICON_NAME_REVERT );
	
	private final JTextComponent fieldText;
	
	private final JScrollPane scroll;
	
	private final Validator<String> validator;
	
	private String initialValue = "";
	
	public LeafTextAreaEditor( Validator<String> validator )
	{
		
		this( validator, false );
	}
	
	public LeafTextAreaEditor( Validator<String> validator, boolean textField )
	{
		this.validator = validator;
		fieldText = textField ? new JTextField() : new JTextArea();
		scroll = new JScrollPane(fieldText);
		startupComponents( textField );
		startupLayout( textField );
		placeComponents( textField );
		setupListeners();
		enableButtons( false );
	}
	
	public void setValue( String value )
	{
		this.initialValue = value == null ? "" : value;
		fieldText.setText( initialValue );
	}
	
	private void startupComponents( boolean textField )
	{
		if( !textField )
		{
			((JTextArea) fieldText).setWrapStyleWord( true );
			((JTextArea) fieldText).setLineWrap( true );
		}
		new CopyPasteHandler(fieldText);
		scroll.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
		scroll.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
		buttonSave.setMargin( new Insets(0,0,0,0) );
		buttonRevert.setMargin( new Insets(0,0,0,0) );
	}
	
	private void startupLayout( boolean textField )
	{
		TableLayout layout;
		if( !textField )
		{
			layout = new TableLayout(
					new double[]{ TableLayout.FILL, TableLayout.MINIMUM, TableLayout.MINIMUM },
					new double[]{ TableLayout.MINIMUM, TableLayout.FILL } );
		}
		else
		{
			layout = new TableLayout(
					new double[]{ TableLayout.FILL, TableLayout.MINIMUM, TableLayout.MINIMUM },
					new double[]{ TableLayout.MINIMUM } );
		}
		this.setLayout( layout );
	}
	
	private void placeComponents( boolean textField )
	{
		if( ! textField )
		{
			this.add( scroll, new TableLayoutConstraints( 0, 1, 2, 1) );
			this.add( buttonSave, new TableLayoutConstraints( 1, 0 ) );
			this.add( buttonRevert, new TableLayoutConstraints( 2, 0 ) );
		}
		else
		{
			this.add( fieldText, new TableLayoutConstraints( 0, 0 ) );
			this.add( buttonSave, new TableLayoutConstraints( 1, 0 ) );
			this.add( buttonRevert, new TableLayoutConstraints( 2, 0 ) );
		}
	}
	
	private void setupListeners()
	{
		buttonSave.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				save();
			}
		} );
		buttonRevert.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				revert();
			}
		} );
		fieldText.addCaretListener( new CaretListener()
		{
			@Override
			public void caretUpdate( CaretEvent e )
			{
				enableButtons( !initialValue.equals( fieldText.getText() ) && ( validator == null || validator.isValid( fieldText.getText() ) ) );
			}
		} );
	}
	
	private void enableButtons( boolean enable )
	{
		buttonRevert.setEnabled( enable );
		buttonSave.setEnabled( enable );	
	}
	
	private void save()
	{
		enableButtons( false );
		firePropertyChange( ACTION_SAVE, initialValue, fieldText.getText() );
		initialValue = fieldText.getText();
	}
	
	private void revert()
	{
		fieldText.setText( initialValue );
		enableButtons( false );
		firePropertyChange( ACTION_REVERT, fieldText.getText(), initialValue );
	}
	
	@Override
	public void setEnabled( boolean enabled )
	{
		fieldText.setEnabled( enabled );
		if( enabled )
		{
			fieldText.requestFocusInWindow();
		}
	}
	
}
