/*
 * This file is part of the Vamsas Client version 0.2. 
 * Copyright 2010 by Jim Procter, Iain Milne, Pierre Marguerite, 
 *  Andrew Waterhouse and Dominik Lindner.
 * 
 * Earlier versions have also been incorporated into Jalview version 2.4 
 * since 2008, and TOPALi version 2 since 2007.
 * 
 * The Vamsas Client is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * The Vamsas Client 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.
 */
package uk.ac.vamsas.objects.utils;

import java.util.Enumeration;
import java.util.Vector;

import uk.ac.vamsas.objects.core.Property;

public class Properties {
  public static Property newProperty(String name, String type, String content) {
    Property vProperty = new Property();
    vProperty.setName(name);
    if (type != null) {
      vProperty.setType(type);
    } else {
      vProperty.setType(STRINGTYPE);
    }
    vProperty.setContent(content);
    return vProperty;
  }

  final public static String STRINGTYPE = "string";

  final public static String FLOATTYPE = "float";

  final public static String INTEGERTYPE = "integer";

  final public static String BOOLEANTYPE = "boolean";

  /**
   * add newprop to properties, or update the value of an existing property with
   * the same exact name and type. Note - this routine will stop after
   * encounting the first occurance of a Property with the same name and type,
   * no others will be affected.
   * 
   * @param properties
   * @param newprop
   * @return true if property was added or its value updated. false if no change
   *         was made.
   */
  public static boolean addOrReplace(Vector properties, Property newprop) {
    if (properties.size() > 0) {
      Enumeration en = properties.elements();
      while (en.hasMoreElements()) {
        Object el = en.nextElement();
        if (el instanceof Property) {
          Property prop = (Property) el;
          if (prop.getName().equals(newprop.getName())
              && prop.getType().equals(newprop.getType())) {
            if (prop.getContent().equals(newprop.getContent())) {
              return false;
            } else {
              prop.setContent(newprop.getContent());
              return true;
            }
          }
        } else {
          throw new Error(
              "Implementation Error: properties must be a Vector of uk.ac.vamsas.objects.core.Property objects only.");
        }
      }
    }
    properties.addElement(newprop);
    return true;
  }

  /**
   * validate property p against the known type strings and try to parse the
   * content string accordingly
   * 
   * @param p
   * @return true if the content parses as the given type (if it is known) TODO:
   *         decide if an isValidType method is also necessary.
   */
  public static boolean isValid(Property p) {
    if (p.getType().equalsIgnoreCase(STRINGTYPE)) {
      return true;
    } else if (p.getType().equalsIgnoreCase(BOOLEANTYPE)) {
      try {
        Boolean bool = new Boolean(p.getContent());
        return true;
      } catch (Exception e) {
        return false;
      }
    } else if (p.getType().equalsIgnoreCase(FLOATTYPE)) {
      try {
        Float fv = new Float(p.getContent());
        return true;
      } catch (Exception e) {
        return false;
      }
    } else if (p.getType().equalsIgnoreCase(INTEGERTYPE)) {

      try {
        Integer fv = new Integer(p.getContent());
        return true;
      } catch (Exception e) {
        return false;
      }
    }
    return false;
  }

  /**
   * String content test
   * 
   * @param p
   * @return true if the property is a string
   */
  public static boolean isString(Property p) {
    return isType(p, STRINGTYPE);
  }

  /**
   * Float content test
   * 
   * @param p
   * @return true if the property is a string
   */
  public static boolean isFloat(Property p) {
    return isType(p, FLOATTYPE);
  }

  /**
   * Integer content test
   * 
   * @param p
   * @return true if the property is a string
   */
  public static boolean isInteger(Property p) {
    return isType(p, INTEGERTYPE);
  }

  /**
   * Boolean content test
   * 
   * @param p
   * @return true if the property is a string
   */
  public static boolean isBoolean(Property p) {
    return isType(p, BOOLEANTYPE);
  }

  /**
   * 
   * @param p
   *          the property to test for type
   * @param typeString
   *          one of the string constants in this class
   * @return true if p is of type 'typeString'
   */
  public static boolean isType(Property p, String typeString) {
    return (p == null) ? false : (p.getType().toLowerCase().equals(typeString));
  }

}
