/*
 * AddressBookMultiLineField.java
 *
 * Copyright 2013 John W Dawson
 *
 * This code is distributed under the terms of the GNU General Public License, version 3
 *
 * This class represents a multi-line field on the data entry tabs
 */
 
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.util.regex.*;
import java.util.*;
import java.util.logging.*;
import javax.naming.directory.*;
public class AddressBookMultiLineField extends JScrollPane implements AddressBookField
{
  static final int DEFAULT_FIELD_WIDTH = 36;
  private static Pattern fieldPattern = Pattern.compile ("%(\\w+)%");
  private static Pattern escapePattern = Pattern.compile ("\\\\(.)");
  private JTextArea textArea;
  private String id;
  private String ldapAttribute;
  private Boolean required;
  private String fieldLabel;
  private Map<String, AddressBookField> fieldList;
  private Container panel;
  private EditPanel tabs;
  private ArrayList<DocumentListener> listeners = new ArrayList<DocumentListener> ();
  static Logger log = Logger.getLogger ("LdapAddressBook");
  
  public AddressBookMultiLineField (ConfigurationRecord fieldConfiguration, Map<String, AddressBookField> fieldList)
  {
    super (VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER);
    
    this.id = fieldConfiguration.getElementValue ("id");
    
    // Default value & validation not allowed for multi-line fields
    if (fieldConfiguration.getElementValue ("default") != null)
    {
      JOptionPane.showMessageDialog 
        (null, "Multi-line field \"" + this.id + "\" cannot have default value",
         "Invalid Configuration Data", JOptionPane.ERROR_MESSAGE);
      System.exit (0);
    }
    if (fieldConfiguration.getElementValue ("validation") != null)
    {
      JOptionPane.showMessageDialog 
        (null, "Multi-line field \"" + this.id + "\" cannot have validation pattern",
         "Invalid Configuration Data", JOptionPane.ERROR_MESSAGE);
      System.exit (0);
    }
    
    // Create the text area, which will be displayed within the scroll pane
    this.textArea = new JTextArea ((int)fieldConfiguration.getIntegerValue ("numlines"), DEFAULT_FIELD_WIDTH);
    this.setViewportView (this.textArea);
    
    this.ldapAttribute = fieldConfiguration.getElementValue ("ldapattribute");
    this.required = fieldConfiguration.getBooleanValue ("required");
    this.fieldLabel = fieldConfiguration.getElementValue ("label");
    this.fieldList = fieldList;
  }
  
  public void initialise ()
  {
    // Field is initially disabled
    this.textArea.setEnabled (false);
    this.textArea.setDisabledTextColor (Color.BLACK);
    
    this.panel = getParent();
    this.tabs = (EditPanel) panel.getParent();
    
  }
  
  public void displayValue (SearchResult entry)
  {
  
    // Disable all document listeners so this change is ignored
    disableListeners ();
    
    // Get value from entry and set field text
    this.textArea.setText (getValue (entry));
    
    // Re-enable the listners
    enableListeners ();
  }  
  
  public void clear ()
  {
    this.textArea.setText ("");
  }  
  
  public Boolean requiredEmpty ()
  {
    if (required && this.textArea.getText().length() == 0)
    {
      // Set focus to this field
      this.setFocus ();
      
      JOptionPane.showMessageDialog 
        (null, "Please enter a value in the " + fieldLabel + " field",
         "Required Field Empty", JOptionPane.ERROR_MESSAGE);
         
      return true;
    }
    else
    {
      return false;
    }
  }
  
  public String getLdapAttribute ()
  {
    return ldapAttribute;
  }
  
  public String getValue (SearchResult entry)
  {
    // Get attribute value from attribute entries
    try
    {   
      return String.valueOf (entry.getAttributes().get(ldapAttribute).get());
    }
    catch (Exception e)
    {
      return null;
    }
  }
  
  public String getLabel ()
  {
    return fieldLabel;
  } 
  
  public void setFocus ()
  { 
    // Return focus to this field (reset tab if necessary)
    tabs.setSelectedComponent (panel);
    this.textArea.requestFocusInWindow ();
  }

  public Boolean validateText ()
  {
    return true;
  }  
   
  public Boolean isDnField ()
  {
    return false;
  }
  
  public Boolean isTerminal ()
  {
    return false;
  }
  
  public void addDocumentListener (DocumentListener listener)
  {
    // Set a handler for changes to this field
    this.textArea.getDocument().addDocumentListener (listener);
    
    // Add handler to list
    listeners.add (listener);
    
  }
  
  private void disableListeners ()
  {
    // Temporarily disable all handlers listening for changes to this field
    for (DocumentListener listener : listeners)
    {
      this.textArea.getDocument().removeDocumentListener (listener);
    }
  }
  
  private void enableListeners ()
  {
    // Re-enable all handlers listening for changes to this field
    for (DocumentListener listener : listeners)
    {
      this.textArea.getDocument().addDocumentListener (listener);
    }
  }
  
  public void setDnField (Boolean terminal)
  {}
  
  public String getText()
  {
    return this.textArea.getText();
  }
  
  public byte [] getBinary()
  {
    return null;
  }
  
  public void setText(String t)
  {
    this.textArea.setText(t);
  }
  
  public void setEnabled (boolean enabled)
  {
    this.textArea.setEnabled (enabled);
  }
    
  public CallButton getCallButton ()
  {
    return null;
  }    
  public void enableCallButton () {};
  public void disableCallButton () {};
  
}
       