/** \file config_param.cpp .
-----------------------------------------------------------------------------

 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.

-----------------------------------------------------------------------------

   Description: Resource Specifier Classes for Text Analysis Engines

-----------------------------------------------------------------------------


   01/30/2003  Initial creation

-------------------------------------------------------------------------- */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------

#include "uima/pragmas.hpp" //must be first to surpress warnings
#include "uima/config_param.hpp"
#include "uima/err_ids.h"
#include "uima/msg.h"

#include <vector>

namespace uima {

  UIMA_EXC_CLASSIMPLEMENT(ConfigException, Exception);
  UIMA_EXC_CLASSIMPLEMENT(ConfigParamException, ConfigException);

  ConfigurationGroup::~ConfigurationGroup() {
    map<icu::UnicodeString, ConfigurationParameter *>::iterator entries = iv_configParams.begin();
    while (entries != iv_configParams.end()) {
      delete (*entries).second;
      entries++;
    }
  }

  const vector <const ConfigurationParameter *> ConfigurationGroup::getConfigurationParameters() const {
    vector <const ConfigurationParameter *> params;
    map<icu::UnicodeString, ConfigurationParameter *>::const_iterator ite;
    for (ite = iv_configParams.begin(); ite != iv_configParams.end(); ite++) {
      params.push_back(ite->second);
    }
    return params;
  }

  bool ConfigurationParameter::isDefinedForAnnotatorContext(const icu::UnicodeString & ancKey) const {
    if (iv_vecRestrictedToDelegates.size() == 0 //there are no restrictions
        || ancKey == "") {//the request is from the AnC itself, not a delegate
      return true;
    }
    bool found = false;
    size_t i = 0;
    while (!found && i < iv_vecRestrictedToDelegates.size()) {
      found = (ancKey.compare(iv_vecRestrictedToDelegates[i]) == 0);
      i++;
    }
    return found;
  }



  vector<NameValuePair const *> SettingsForGroup::getNameValuePairs() const {
    vector <const NameValuePair *> params;
    map<icu::UnicodeString, NameValuePair *>::const_iterator ite;
    for (ite = iv_nameValuePairs.begin(); ite != iv_nameValuePairs.end(); ite++) {
      params.push_back(ite->second);
    }
    return params;

  }


  NameValuePair::NameValuePair()
      :MetaDataObject(),
      iv_name(),
      iv_enType(ConfigurationParameter::INTEGER),
      iv_enAggregation(ConfigurationParameter::SINGLE_VALUE) {
    reset();
  }

  void NameValuePair::reset() {
    iv_strValues.clear();
    iv_intValues.clear();
    iv_fltValues.clear();
    iv_boolValues.clear();
    if (!iv_enAggregation) {
      switch (iv_enType) {
      case ConfigurationParameter::STRING  :
        iv_strValues.push_back(icu::UnicodeString());
        break;
      case ConfigurationParameter::INTEGER :
        iv_intValues.push_back((int) 0);
        break;
      case ConfigurationParameter::FLOAT   :
        iv_fltValues.push_back((float)0.0);
        break;
      case ConfigurationParameter::BOOLEAN :
        iv_boolValues.push_back(false);
        break;
      default:
        assertWithMsg(false, "Unexpected (new?) value for enum ConfigurationParameter");
      }
    }
  }
  void NameValuePair::define(ConfigurationParameter::EnParameterType enType, ConfigurationParameter::EnParameterAggregation enIsMulti) {
    iv_enType = enType;
    iv_enAggregation = enIsMulti;
    reset();
  }

  size_t NameValuePair::size() const {
    switch (iv_enType) {
    case ConfigurationParameter::STRING  :
      return iv_strValues.size();
    case ConfigurationParameter::INTEGER :
      return iv_intValues.size();
    case ConfigurationParameter::FLOAT   :
      return iv_fltValues.size();
    case ConfigurationParameter::BOOLEAN :
      return iv_boolValues.size();
    }
    assertWithMsg(false, "Unexpected (new?) value for enum ConfigurationParameter");
    return 0;
  }

  TyErrorId NameValuePair::setValue(int value) {
    ensureType(ConfigurationParameter::INTEGER);
    ensureSingleValue();
    iv_intValues[0] = value;
    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::setValue(float value) {
    ensureType(ConfigurationParameter::FLOAT);
    ensureSingleValue();
    iv_fltValues[0] = value;
    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::setValue(bool value) {
    ensureType(ConfigurationParameter::BOOLEAN);
    ensureSingleValue();
    iv_boolValues[0] = value;
    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::setValue(const icu::UnicodeString & value) {
    ensureSingleValue();
    switch (iv_enType) {
    case ConfigurationParameter::STRING  :
      iv_strValues[0] = value;
      break;
    case ConfigurationParameter::INTEGER :
      iv_intValues[0] = (int) string2Long(convert(value));
      break;
    case ConfigurationParameter::FLOAT   :
      iv_fltValues[0] = (float)string2Double(convert(value));
      break;
    case ConfigurationParameter::BOOLEAN :
      iv_boolValues[0] = string2Bool(convert(value));
      break;
    default:
      assertWithMsg(false, "Unexpected (new?) value for enum ConfigurationParameter");
    }

    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::addValue(int value) {
    ensureType(ConfigurationParameter::INTEGER);
    ensureMultipleValues();
    iv_intValues.push_back(value);
    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::addValue(float value) {
    ensureType(ConfigurationParameter::FLOAT);
    ensureMultipleValues();
    iv_fltValues.push_back(value);
    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::addValue(bool value) {
    ensureType(ConfigurationParameter::BOOLEAN);
    ensureMultipleValues();
    iv_boolValues.push_back(value);
    return UIMA_ERR_NONE;
  }

  TyErrorId NameValuePair::addValue(const icu::UnicodeString & value) {
    ensureMultipleValues();
    switch (iv_enType) {
    case ConfigurationParameter::STRING  :
      iv_strValues.push_back(value);
      break;
    case ConfigurationParameter::INTEGER :
      iv_intValues.push_back((int) string2Long(convert(value)));
      break;
    case ConfigurationParameter::FLOAT   :
      iv_fltValues.push_back((float)string2Double(convert(value)));
      break;
    case ConfigurationParameter::BOOLEAN :
      iv_boolValues.push_back(string2Bool(convert(value)));
      break;
    default:
      assertWithMsg(false, "Unexpected (new?) value for enum ConfigurationParameter");
    }

    return UIMA_ERR_NONE;
  }

  void NameValuePair::ensureType(ConfigurationParameter::EnParameterType t) const {
    if (iv_enType != t) {
      UIMA_EXC_THROW_NEW(ConfigException,
                         UIMA_ERR_CONFIG_INVALID_EXTRACTOR_FOR_TYPE,
                         UIMA_MSG_ID_EXC_CONFIG_VALUE_TYPE_MISMATCH,
                         UIMA_MSG_ID_EXCON_CONFIG_VALUE_EXTRACT,
                         ErrorInfo::recoverable);
    }
  }
  void NameValuePair::ensureSingleValue()  const {
    if (isMultiValued()) {
      UIMA_EXC_THROW_NEW(ConfigException,
                         UIMA_ERR_CONFIG_INVALID_EXTRACTOR_FOR_TYPE,
                         UIMA_MSG_ID_EXC_CONFIG_VALUE_MUST_BE_SINGLE,
                         UIMA_MSG_ID_EXCON_CONFIG_VALUE_EXTRACT,
                         ErrorInfo::recoverable);
    }
    assert(size() == 1);
  }

  void NameValuePair::ensureMultipleValues() const {
    if (!isMultiValued()) {
      UIMA_EXC_THROW_NEW(ConfigException,
                         UIMA_ERR_CONFIG_INVALID_EXTRACTOR_FOR_TYPE,
                         UIMA_MSG_ID_EXC_CONFIG_VALUE_MUST_BE_MULTI,
                         UIMA_MSG_ID_EXCON_CONFIG_VALUE_EXTRACT,
                         ErrorInfo::recoverable);
    }
  }

  bool NameValuePair::extractBoolValue() const {
    ensureType(ConfigurationParameter::BOOLEAN);
    ensureSingleValue();
    return(iv_boolValues[0]);
  }

  vector<bool> const & NameValuePair::extractBoolValues() const {
    ensureType(ConfigurationParameter::BOOLEAN);
    ensureMultipleValues();
    return(iv_boolValues);
  }

  int NameValuePair::extractIntValue() const {
    ensureType(ConfigurationParameter::INTEGER);
    ensureSingleValue();
    return(iv_intValues[0]);
  }

  vector<int> const & NameValuePair::extractIntValues() const {
    ensureType(ConfigurationParameter::INTEGER);
    ensureMultipleValues();
    return(iv_intValues);
  }

  float NameValuePair::extractFloatValue() const {
    ensureType(ConfigurationParameter::FLOAT);
    ensureSingleValue();
    return(iv_fltValues[0]);
  }

  vector<float> const & NameValuePair::extractFloatValues() const {
    ensureType(ConfigurationParameter::FLOAT);
    ensureMultipleValues();
    return(iv_fltValues);
  }

  icu::UnicodeString const & NameValuePair::extractStringValue() const {
    ensureType(ConfigurationParameter::STRING);
    ensureSingleValue();
    return(iv_strValues[0]);
  }

  vector<icu::UnicodeString> const & NameValuePair::extractStringValues() const {
    ensureType(ConfigurationParameter::STRING);
    ensureMultipleValues();
    return(iv_strValues);
  }

  std::string  NameValuePair::extractSingleByteStringValue() const {
    ensureType(ConfigurationParameter::STRING);
    ensureSingleValue();
    //return(convert(iv_strValues[0]));
    //why was this changed? convert reurns a string! (bll)
    std::string svalue( convert(iv_strValues[0]));
    return svalue;
  }

  void NameValuePair::extractSingleByteStringValues( vector<std::string*> &  vecStr ) const  {
    ensureType(ConfigurationParameter::STRING);
    ensureMultipleValues();
    for (size_t i=0; i < iv_strValues.size(); i++) {
      std::string * pvalue = new std::string(convert(iv_strValues[i]));
      vecStr.push_back(pvalue);
    }
  }


  /* inline */ std::string NameValuePair::convert(const icu::UnicodeString & value) const {
    return UnicodeStringRef(value).asUTF8();
  }


} // namespace uima
