/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.config;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * The Class Prop.
 * 
 * @param <V> the value type
 * @version 0.3
 * @since jNPad 0.1
 */
public abstract class Prop<V> implements Serializable {
  /** The name. */
  protected final String                   name;
  
  /** The default value. */
  protected final V                        defaultValue;

  private final List<PropChangeListener<V>> myListeners      = new CopyOnWriteArrayList<PropChangeListener<V>>();

  /** UID */
  private static final long                serialVersionUID = 7741728667044277868L;

  /**
   * Instantiates a new prop.
   * 
   * @param name the name
   * @param def the def
   */
  protected Prop(String name, V def) {
    this.name = name;
    defaultValue = def;
  }

  /**
   * Adds the prop listener.
   *
   * @param listener the listener
   */
  public void addPropListener(PropChangeListener<V> listener) {
    myListeners.add(listener);
  }

  /**
   * Removes the prop listener.
   *
   * @param listener the listener
   */
  public void removePropListener(PropChangeListener<V> listener) {
    myListeners.add(listener);
  }

  /**
   * Fire prop change.
   *
   * @param oldValue the old value
   * @param newValue the new value
   */
  protected void firePropChange(V oldValue, V newValue) {
    if (!myListeners.isEmpty()) {
      PropChangeEvent<V> event = new PropChangeEvent<V>(this, oldValue, newValue);
      for (PropChangeListener<V> listener : myListeners)
        listener.propChange(event);
    }
  }

  /**
   * Gets the name.
   * 
   * @return the name
   */
  public String getName() {
    return name;
  }

  /**
   * Gets the default.
   * 
   * @return the default
   */
  public V getDefault() {
    return defaultValue;
  }
  
  /**
   * Sets the to default.
   */
  public void setToDefault() {
    setValue(defaultValue);
  }
  
  /**
   * Checks if is default.
   *
   * @return true, if is default
   */
  public boolean isDefault() {
    return getDefault().equals(getValue());
  }

  /**
   * Gets the value.
   *
   * @return the value
   */
  public abstract V getValue();
  
  /**
   * Sets the value.
   *
   * @param value the new value
   */
  public void setValue(V value) {
    V oldValue = getValue();
    doSetValue(value);
    firePropChange(oldValue, value);
  }

  /**
   * Do set value.
   *
   * @param value the value
   */
  protected abstract void doSetValue(V value);
  
  /**
   * Gets the default string.
   *
   * @return the default string
   */
  public abstract String getDefaultString();

  /**
   * To string.
   * 
   * @return the string
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return name + "=" + getDefaultString(); //$NON-NLS-1$
  }

}
