package org.apache.solr.schema;
/*
 * 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.
 */

import org.apache.lucene.analysis.util.ResourceLoader;
import org.apache.lucene.analysis.util.ResourceLoaderAware;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.StorableField;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.FieldValueFilter;
import org.apache.lucene.queries.ChainedFilter;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.search.QParser;
import org.apache.solr.search.SolrConstantScoreQuery;
import org.apache.solr.search.function.ValueSourceRangeFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Currency;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Field type for support of monetary values.
 * <p>
 * See <a href="http://wiki.apache.org/solr/CurrencyField">http://wiki.apache.org/solr/CurrencyField</a>
 */
public class CurrencyField extends FieldType implements SchemaAware, ResourceLoaderAware {
  protected static final String PARAM_DEFAULT_CURRENCY      = "defaultCurrency";
  protected static final String PARAM_RATE_PROVIDER_CLASS   = "providerClass";
  protected static final Object PARAM_PRECISION_STEP        = "precisionStep";
  protected static final String DEFAULT_RATE_PROVIDER_CLASS = "solr.FileExchangeRateProvider";
  protected static final String DEFAULT_DEFAULT_CURRENCY    = "USD";
  protected static final String DEFAULT_PRECISION_STEP      = "0";
  protected static final String FIELD_SUFFIX_AMOUNT_RAW     = "_amount_raw";
  protected static final String FIELD_SUFFIX_CURRENCY       = "_currency";

  private IndexSchema schema;
  protected FieldType fieldTypeCurrency;
  protected FieldType fieldTypeAmountRaw;
  private String exchangeRateProviderClass;
  private String defaultCurrency;
  private ExchangeRateProvider provider;
  public static Logger log = LoggerFactory.getLogger(CurrencyField.class);

  /**
   * A wrapper arround <code>Currency.getInstance</code> that returns null
   * instead of throwing <code>IllegalArgumentException</code>
   * if the specified Currency does not exist in this JVM.
   *
   * @see Currency#getInstance(String)
   */
  public static Currency getCurrency(final String code) {
    try {
      return Currency.getInstance(code);
    } catch (IllegalArgumentException e) {
      /* :NOOP: */
    }
    return null;
  }

  @Override
  protected void init(IndexSchema schema, Map<String, String> args) {
    super.init(schema, args);
    if (this.isMultiValued()) { 
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, 
                              "CurrencyField types can not be multiValued: " + 
                              this.typeName);
    }
    this.schema = schema;
    this.exchangeRateProviderClass = args.get(PARAM_RATE_PROVIDER_CLASS);
    this.defaultCurrency = args.get(PARAM_DEFAULT_CURRENCY);

    if (this.defaultCurrency == null) {
      this.defaultCurrency = DEFAULT_DEFAULT_CURRENCY;
    }
    
    if (this.exchangeRateProviderClass == null) {
      this.exchangeRateProviderClass = DEFAULT_RATE_PROVIDER_CLASS;
    }

    if (null == getCurrency(this.defaultCurrency)) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Default currency code is not supported by this JVM: " + this.defaultCurrency);
    }

    String precisionStepString = args.get(PARAM_PRECISION_STEP);
    if (precisionStepString == null) {
      precisionStepString = DEFAULT_PRECISION_STEP;
    }

    // Initialize field type for amount
    fieldTypeAmountRaw = new TrieLongField();
    fieldTypeAmountRaw.setTypeName("amount_raw_type_tlong");
    Map<String,String> map = new HashMap<>(1);
    map.put("precisionStep", precisionStepString);
    fieldTypeAmountRaw.init(schema, map);
    
    // Initialize field type for currency string
    fieldTypeCurrency = new StrField();
    fieldTypeCurrency.setTypeName("currency_type_string");
    fieldTypeCurrency.init(schema, new HashMap<String,String>());
    
    args.remove(PARAM_RATE_PROVIDER_CLASS);
    args.remove(PARAM_DEFAULT_CURRENCY);
    args.remove(PARAM_PRECISION_STEP);

    try {
      Class<? extends ExchangeRateProvider> c = schema.getResourceLoader().findClass(exchangeRateProviderClass, ExchangeRateProvider.class);
      provider = c.newInstance();
      provider.init(args);
    } catch (Exception e) {
      throw new SolrException(ErrorCode.BAD_REQUEST, "Error instantiating exchange rate provider "+exchangeRateProviderClass+": " + e.getMessage(), e);
    }
  }

  @Override
  public boolean isPolyField() {
    return true;
  }

  @Override
  public void checkSchemaField(final SchemaField field) throws SolrException {
    super.checkSchemaField(field);
    if (field.multiValued()) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, 
                              "CurrencyFields can not be multiValued: " + 
                              field.getName());
    }
  }

  @Override
  public List<StorableField> createFields(SchemaField field, Object externalVal, float boost) {
    CurrencyValue value = CurrencyValue.parse(externalVal.toString(), defaultCurrency);

    List<StorableField> f = new ArrayList<>();
    SchemaField amountField = getAmountField(field);
    f.add(amountField.createField(String.valueOf(value.getAmount()), amountField.indexed() && !amountField.omitNorms() ? boost : 1F));
    SchemaField currencyField = getCurrencyField(field);
    f.add(currencyField.createField(value.getCurrencyCode(), currencyField.indexed() && !currencyField.omitNorms() ? boost : 1F));

    if (field.stored()) {
      org.apache.lucene.document.FieldType customType = new org.apache.lucene.document.FieldType();
      assert !customType.omitNorms();
      customType.setStored(true);
      String storedValue = externalVal.toString().trim();
      if (storedValue.indexOf(",") < 0) {
        storedValue += "," + defaultCurrency;
      }
      f.add(createField(field.getName(), storedValue, customType, 1F));
    }

    return f;
  }

  private SchemaField getAmountField(SchemaField field) {
    return schema.getField(field.getName() + POLY_FIELD_SEPARATOR + FIELD_SUFFIX_AMOUNT_RAW);
  }

  private SchemaField getCurrencyField(SchemaField field) {
    return schema.getField(field.getName() + POLY_FIELD_SEPARATOR + FIELD_SUFFIX_CURRENCY);
  }

  private void createDynamicCurrencyField(String suffix, FieldType type) {
    String name = "*" + POLY_FIELD_SEPARATOR + suffix;
    Map<String, String> props = new HashMap<>();
    props.put("indexed", "true");
    props.put("stored", "false");
    props.put("multiValued", "false");
    props.put("omitNorms", "true");
    int p = SchemaField.calcProps(name, type, props);
    schema.registerDynamicFields(SchemaField.create(name, type, p, null));
  }

  /**
   * When index schema is informed, add dynamic fields "*____currency" and "*____amount_raw". 
   * 
   * {@inheritDoc}
   * 
   * @param schema {@inheritDoc}
   */
  @Override
  public void inform(IndexSchema schema) {
    this.schema = schema;
    createDynamicCurrencyField(FIELD_SUFFIX_CURRENCY,   fieldTypeCurrency);
    createDynamicCurrencyField(FIELD_SUFFIX_AMOUNT_RAW, fieldTypeAmountRaw);
  }

  /**
   * Load the currency config when resource loader initialized.
   *
   * @param resourceLoader The resource loader.
   */
  @Override
  public void inform(ResourceLoader resourceLoader) {
    provider.inform(resourceLoader);
    boolean reloaded = provider.reload();
    if(!reloaded) {
      log.warn("Failed reloading currencies");
    }
  }

  @Override
  public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
    CurrencyValue value = CurrencyValue.parse(externalVal, defaultCurrency);
    CurrencyValue valueDefault;
    valueDefault = value.convertTo(provider, defaultCurrency);

    return getRangeQuery(parser, field, valueDefault, valueDefault, true, true);
  }

  /**
   * <p>
   * Returns a ValueSource over this field in which the numeric value for 
   * each document represents the indexed value as converted to the default 
   * currency for the field, normalized to it's most granular form based 
   * on the default fractional digits.
   * </p>
   * <p>
   * For example: If the default Currency specified for a field is 
   * <code>USD</code>, then the values returned by this value source would 
   * represent the equivilent number of "cents" (ie: value in dollars * 100) 
   * after converting each document's native currency to USD -- because the 
   * default fractional digits for <code>USD</code> is "<code>2</code>".  
   * So for a document whose indexed value was currently equivilent to 
   * "<code>5.43,USD</code>" using the the exchange provider for this field, 
   * this ValueSource would return a value of "<code>543</code>"
   * </p>
   *
   * @see #PARAM_DEFAULT_CURRENCY
   * @see #DEFAULT_DEFAULT_CURRENCY
   * @see Currency#getDefaultFractionDigits
   * @see #getConvertedValueSource
   */
  public RawCurrencyValueSource getValueSource(SchemaField field, 
                                               QParser parser) {
    field.checkFieldCacheSource(parser);
    return new RawCurrencyValueSource(field, defaultCurrency, parser);
  }

  /**
   * <p>
   * Returns a ValueSource over this field in which the numeric value for 
   * each document represents the value from the underlying 
   * <code>RawCurrencyValueSource</code> as converted to the specified target 
   * Currency.
   * </p>
   * <p>
   * For example: If the <code>targetCurrencyCode</code> param is set to
   * <code>USD</code>, then the values returned by this value source would 
   * represent the equivilent number of dollars after converting each 
   * document's raw value to <code>USD</code>.  So for a document whose 
   * indexed value was currently equivilent to "<code>5.43,USD</code>" 
   * using the the exchange provider for this field, this ValueSource would 
   * return a value of "<code>5.43</code>"
   * </p>
   *
   * @param targetCurrencyCode The target currency for the resulting value source, if null the defaultCurrency for this field type will be used
   * @param source the raw ValueSource to wrap
   * @see #PARAM_DEFAULT_CURRENCY
   * @see #DEFAULT_DEFAULT_CURRENCY
   * @see #getValueSource
   */
  public ValueSource getConvertedValueSource(String targetCurrencyCode, 
                                             RawCurrencyValueSource source) {
    if (null == targetCurrencyCode) { 
      targetCurrencyCode = defaultCurrency; 
    }
    return new ConvertedCurrencyValueSource(targetCurrencyCode, 
                                            source);
  }

  @Override
  public Query getRangeQuery(QParser parser, SchemaField field, String part1, String part2, final boolean minInclusive, final boolean maxInclusive) {
      final CurrencyValue p1 = CurrencyValue.parse(part1, defaultCurrency);
      final CurrencyValue p2 = CurrencyValue.parse(part2, defaultCurrency);

      if (p1 != null && p2 != null && !p1.getCurrencyCode().equals(p2.getCurrencyCode())) {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                  "Cannot parse range query " + part1 + " to " + part2 +
                          ": range queries only supported when upper and lower bound have same currency.");
      }

      return getRangeQuery(parser, field, p1, p2, minInclusive, maxInclusive);
  }

  public Query getRangeQuery(QParser parser, SchemaField field, final CurrencyValue p1, final CurrencyValue p2, final boolean minInclusive, final boolean maxInclusive) {
    String currencyCode = (p1 != null) ? p1.getCurrencyCode() :
                          (p2 != null) ? p2.getCurrencyCode() : defaultCurrency;

    // ValueSourceRangeFilter doesn't check exists(), so we have to
    final Filter docsWithValues = new FieldValueFilter(getAmountField(field).getName());
    final Filter vsRangeFilter = new ValueSourceRangeFilter
      (new RawCurrencyValueSource(field, currencyCode, parser),
       p1 == null ? null : p1.getAmount() + "", 
       p2 == null ? null : p2.getAmount() + "",
       minInclusive, maxInclusive);
    final Filter docsInRange = new ChainedFilter
      (new Filter [] { docsWithValues, vsRangeFilter }, ChainedFilter.AND);

    return new SolrConstantScoreQuery(docsInRange);
    
  }

  @Override
  public SortField getSortField(SchemaField field, boolean reverse) {
    // Convert all values to default currency for sorting.
    return (new RawCurrencyValueSource(field, defaultCurrency, null)).getSortField(reverse);
  }

  @Override
  public void write(TextResponseWriter writer, String name, StorableField field) throws IOException {
    writer.writeStr(name, field.stringValue(), true);
  }

  public ExchangeRateProvider getProvider() {
    return provider;
  }

  /**
   * <p>
   * A value source whose values represent the "normal" values
   * in the specified target currency.
   * </p>
   * @see RawCurrencyValueSource
   */
  class ConvertedCurrencyValueSource extends ValueSource {
    private final Currency targetCurrency;
    private final RawCurrencyValueSource source;
    private final double rate;
    public ConvertedCurrencyValueSource(String targetCurrencyCode, 
                                        RawCurrencyValueSource source) {
      this.source = source;
      this.targetCurrency = getCurrency(targetCurrencyCode);
      if (null == targetCurrency) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + targetCurrencyCode);
      }
      // the target digits & currency of our source, 
      // become the source digits & currency of ourselves
      this.rate = provider.getExchangeRate
        (source.getTargetCurrency().getCurrencyCode(), 
         targetCurrency.getCurrencyCode());
    }

    @Override
    public FunctionValues getValues(Map context, AtomicReaderContext reader) 
      throws IOException {
      final FunctionValues amounts = source.getValues(context, reader);
      // the target digits & currency of our source, 
      // become the source digits & currency of ourselves
      final String sourceCurrencyCode = source.getTargetCurrency().getCurrencyCode();
      final int sourceFractionDigits = source.getTargetCurrency().getDefaultFractionDigits();
      final double divisor = Math.pow(10D, targetCurrency.getDefaultFractionDigits());
      return new FunctionValues() {
        @Override
        public boolean exists(int doc) {
          return amounts.exists(doc);
        }
        @Override
        public long longVal(int doc) {
          return (long) doubleVal(doc);
        }
        @Override
        public int intVal(int doc) {
          return (int) doubleVal(doc);
        }

        @Override
        public double doubleVal(int doc) {
          return CurrencyValue.convertAmount(rate, sourceCurrencyCode, amounts.longVal(doc), targetCurrency.getCurrencyCode()) / divisor;
        }

        @Override
        public float floatVal(int doc) {
          return CurrencyValue.convertAmount(rate, sourceCurrencyCode, amounts.longVal(doc), targetCurrency.getCurrencyCode()) / ((float)divisor);
        }

        @Override
        public String strVal(int doc) {
          return Double.toString(doubleVal(doc));
        }

        @Override
        public String toString(int doc) {
          return name() + '(' + strVal(doc) + ')';
        }
      };
    }
    public String name() {
      return "currency";
    }

    @Override
    public String description() {
      return name() + "(" + source.getField().getName() + "," + targetCurrency.getCurrencyCode()+")";
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      ConvertedCurrencyValueSource that = (ConvertedCurrencyValueSource) o;

      return !(source != null ? !source.equals(that.source) : that.source != null) &&
        (rate == that.rate) && 
        !(targetCurrency != null ? !targetCurrency.equals(that.targetCurrency) : that.targetCurrency != null);

    }

    @Override
    public int hashCode() {
      int result = targetCurrency != null ? targetCurrency.hashCode() : 0;
      result = 31 * result + (source != null ? source.hashCode() : 0);
      result = 31 * (int) Double.doubleToLongBits(rate);
      return result;
    }
  }

  /**
   * <p>
   * A value source whose values represent the "raw" (ie: normalized using 
   * the number of default fractional digits) values in the specified 
   * target currency).
   * </p>
   * <p>
   * For example: if the specified target currency is "<code>USD</code>" 
   * then the numeric values are the number of pennies in the value 
   * (ie: <code>$n * 100</code>) since the number of defalt fractional 
   * digits for <code>USD</code> is "<code>2</code>")
   * </p>
   * @see ConvertedCurrencyValueSource
   */
  class RawCurrencyValueSource extends ValueSource {
    private static final long serialVersionUID = 1L;
    private final Currency targetCurrency;
    private ValueSource currencyValues;
    private ValueSource amountValues;
    private final SchemaField sf;

    public RawCurrencyValueSource(SchemaField sfield, String targetCurrencyCode, QParser parser) {
      this.sf = sfield;
      this.targetCurrency = getCurrency(targetCurrencyCode);
      if (null == targetCurrency) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + targetCurrencyCode);
      }

      SchemaField amountField = schema.getField(sf.getName() + POLY_FIELD_SEPARATOR + FIELD_SUFFIX_AMOUNT_RAW);
      SchemaField currencyField = schema.getField(sf.getName() + POLY_FIELD_SEPARATOR + FIELD_SUFFIX_CURRENCY);

      currencyValues = currencyField.getType().getValueSource(currencyField, parser);
      amountValues = amountField.getType().getValueSource(amountField, parser);
    }
    
    public SchemaField getField() { return sf; }
    public Currency getTargetCurrency() { return targetCurrency; }

    @Override
    public FunctionValues getValues(Map context, AtomicReaderContext reader) throws IOException {
      final FunctionValues amounts = amountValues.getValues(context, reader);
      final FunctionValues currencies = currencyValues.getValues(context, reader);

      return new FunctionValues() {
        private final int MAX_CURRENCIES_TO_CACHE = 256;
        private final int[] fractionDigitCache = new int[MAX_CURRENCIES_TO_CACHE];
        private final String[] currencyOrdToCurrencyCache = new String[MAX_CURRENCIES_TO_CACHE];
        private final double[] exchangeRateCache = new double[MAX_CURRENCIES_TO_CACHE];
        private int targetFractionDigits = -1;
        private int targetCurrencyOrd = -1;
        private boolean initializedCache;

        private String getDocCurrencyCode(int doc, int currencyOrd) {
          if (currencyOrd < MAX_CURRENCIES_TO_CACHE) {
            String currency = currencyOrdToCurrencyCache[currencyOrd];

            if (currency == null) {
              currencyOrdToCurrencyCache[currencyOrd] = currency = currencies.strVal(doc);
            }
            
            if (currency == null) {
              currency = defaultCurrency;
            }

            if (targetCurrencyOrd == -1 && 
                currency.equals(targetCurrency.getCurrencyCode() )) {
              targetCurrencyOrd = currencyOrd;
            }

            return currency;
          } else {
            return currencies.strVal(doc);
          }
        }
        /** throws a (Server Error) SolrException if the code is not valid */
        private Currency getDocCurrency(int doc, int currencyOrd) {
          String code = getDocCurrencyCode(doc, currencyOrd);
          Currency c = getCurrency(code);
          if (null == c) {
            throw new SolrException
              (SolrException.ErrorCode.SERVER_ERROR, 
               "Currency code of document is not supported by this JVM: "+code);
          }
          return c;
        }

        @Override
        public boolean exists(int doc) {
          return amounts.exists(doc);
        }
        
        @Override
        public long longVal(int doc) {
          long amount = amounts.longVal(doc);
          // bail fast using whatever ammounts defaults to if no value
          // (if we don't do this early, currencyOrd may be < 0, 
          // causing index bounds exception
          if ( ! exists(doc) ) {
            return amount;
          }

          if (!initializedCache) {
            for (int i = 0; i < fractionDigitCache.length; i++) {
              fractionDigitCache[i] = -1;
            }

            initializedCache = true;
          }

          int currencyOrd = currencies.ordVal(doc);

          if (currencyOrd == targetCurrencyOrd) {
            return amount;
          }

          double exchangeRate;
          int sourceFractionDigits;

          if (targetFractionDigits == -1) {
            targetFractionDigits = targetCurrency.getDefaultFractionDigits();
          }

          if (currencyOrd < MAX_CURRENCIES_TO_CACHE) {
            exchangeRate = exchangeRateCache[currencyOrd];

            if (exchangeRate <= 0.0) {
              String sourceCurrencyCode = getDocCurrencyCode(doc, currencyOrd);
              exchangeRate = exchangeRateCache[currencyOrd] = provider.getExchangeRate(sourceCurrencyCode, targetCurrency.getCurrencyCode());
            }

            sourceFractionDigits = fractionDigitCache[currencyOrd];

            if (sourceFractionDigits == -1) {
              sourceFractionDigits = fractionDigitCache[currencyOrd] = getDocCurrency(doc, currencyOrd).getDefaultFractionDigits();
            }
          } else {
            Currency source = getDocCurrency(doc, currencyOrd);
            exchangeRate = provider.getExchangeRate(source.getCurrencyCode(), targetCurrency.getCurrencyCode());
            sourceFractionDigits = source.getDefaultFractionDigits();
          }

          return CurrencyValue.convertAmount(exchangeRate, sourceFractionDigits, amount, targetFractionDigits);
        }

        @Override
        public int intVal(int doc) {
          return (int) longVal(doc);
        }

        @Override
        public double doubleVal(int doc) {
          return (double) longVal(doc);
        }

        @Override
        public float floatVal(int doc) {
          return (float) longVal(doc);
        }

        @Override
        public String strVal(int doc) {
          return Long.toString(longVal(doc));
        }

        @Override
        public String toString(int doc) {
          return name() + '(' + amounts.toString(doc) + ',' + currencies.toString(doc) + ')';
        }
      };
    }

    public String name() {
      return "rawcurrency";
    }

    @Override
    public String description() {
      return name() + "(" + sf.getName() + 
        ",target="+targetCurrency.getCurrencyCode()+")";
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      RawCurrencyValueSource that = (RawCurrencyValueSource) o;

      return !(amountValues != null ? !amountValues.equals(that.amountValues) : that.amountValues != null) &&
              !(currencyValues != null ? !currencyValues.equals(that.currencyValues) : that.currencyValues != null) &&
              !(targetCurrency != null ? !targetCurrency.equals(that.targetCurrency) : that.targetCurrency != null);

    }

    @Override
    public int hashCode() {
      int result = targetCurrency != null ? targetCurrency.hashCode() : 0;
      result = 31 * result + (currencyValues != null ? currencyValues.hashCode() : 0);
      result = 31 * result + (amountValues != null ? amountValues.hashCode() : 0);
      return result;
    }
  }
}

/**
 * Configuration for currency. Provides currency exchange rates.
 */
class FileExchangeRateProvider implements ExchangeRateProvider {
  public static Logger log = LoggerFactory.getLogger(FileExchangeRateProvider.class);
  protected static final String PARAM_CURRENCY_CONFIG       = "currencyConfig";

  // Exchange rate map, maps Currency Code -> Currency Code -> Rate
  private Map<String, Map<String, Double>> rates = new HashMap<>();

  private String currencyConfigFile;
  private ResourceLoader loader;

  /**
   * Returns the currently known exchange rate between two currencies. If a direct rate has been loaded,
   * it is used. Otherwise, if a rate is known to convert the target currency to the source, the inverse
   * exchange rate is computed.
   *
   * @param sourceCurrencyCode The source currency being converted from.
   * @param targetCurrencyCode The target currency being converted to.
   * @return The exchange rate.
   * @throws SolrException if the requested currency pair cannot be found
   */
  @Override
  public double getExchangeRate(String sourceCurrencyCode, String targetCurrencyCode) {
    if (sourceCurrencyCode == null || targetCurrencyCode == null) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot get exchange rate; currency was null.");
    }
    
    if (sourceCurrencyCode.equals(targetCurrencyCode)) {
      return 1.0;
    }

    Double directRate = lookupRate(sourceCurrencyCode, targetCurrencyCode);

    if (directRate != null) {
      return directRate;
    }

    Double symmetricRate = lookupRate(targetCurrencyCode, sourceCurrencyCode);

    if (symmetricRate != null) {
      return 1.0 / symmetricRate;
    }

    throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No available conversion rate between " + sourceCurrencyCode + " to " + targetCurrencyCode);
  }

  /**
   * Looks up the current known rate, if any, between the source and target currencies.
   *
   * @param sourceCurrencyCode The source currency being converted from.
   * @param targetCurrencyCode The target currency being converted to.
   * @return The exchange rate, or null if no rate has been registered.
   */
  private Double lookupRate(String sourceCurrencyCode, String targetCurrencyCode) {
    Map<String, Double> rhs = rates.get(sourceCurrencyCode);

    if (rhs != null) {
      return rhs.get(targetCurrencyCode);
    }

    return null;
  }

  /**
   * Registers the specified exchange rate.
   *
   * @param ratesMap           The map to add rate to
   * @param sourceCurrencyCode The source currency.
   * @param targetCurrencyCode The target currency.
   * @param rate               The known exchange rate.
   */
  private void addRate(Map<String, Map<String, Double>> ratesMap, String sourceCurrencyCode, String targetCurrencyCode, double rate) {
    Map<String, Double> rhs = ratesMap.get(sourceCurrencyCode);

    if (rhs == null) {
      rhs = new HashMap<>();
      ratesMap.put(sourceCurrencyCode, rhs);
    }

    rhs.put(targetCurrencyCode, rate);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    FileExchangeRateProvider that = (FileExchangeRateProvider) o;

    return !(rates != null ? !rates.equals(that.rates) : that.rates != null);
  }

  @Override
  public int hashCode() {
    return rates != null ? rates.hashCode() : 0;
  }

  @Override
  public String toString() {
    return "["+this.getClass().getName()+" : " + rates.size() + " rates.]";
  }

  @Override
  public Set<String> listAvailableCurrencies() {
    Set<String> currencies = new HashSet<>();
    for(String from : rates.keySet()) {
      currencies.add(from);
      for(String to : rates.get(from).keySet()) {
        currencies.add(to);
      }
    }
    return currencies;
  }

  @Override
  public boolean reload() throws SolrException {
    InputStream is = null;
    Map<String, Map<String, Double>> tmpRates = new HashMap<>();
    try {
      log.info("Reloading exchange rates from file "+this.currencyConfigFile);

      is = loader.openResource(currencyConfigFile);
      javax.xml.parsers.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      try {
        dbf.setXIncludeAware(true);
        dbf.setNamespaceAware(true);
      } catch (UnsupportedOperationException e) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "XML parser doesn't support XInclude option", e);
      }
      
      try {
        Document doc = dbf.newDocumentBuilder().parse(is);
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        
        // Parse exchange rates.
        NodeList nodes = (NodeList) xpath.evaluate("/currencyConfig/rates/rate", doc, XPathConstants.NODESET);
        
        for (int i = 0; i < nodes.getLength(); i++) {
          Node rateNode = nodes.item(i);
          NamedNodeMap attributes = rateNode.getAttributes();
          Node from = attributes.getNamedItem("from");
          Node to = attributes.getNamedItem("to");
          Node rate = attributes.getNamedItem("rate");
          
          if (from == null || to == null || rate == null) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Exchange rate missing attributes (required: from, to, rate) " + rateNode);
          }
          
          String fromCurrency = from.getNodeValue();
          String toCurrency = to.getNodeValue();
          Double exchangeRate;
          
          if (null == CurrencyField.getCurrency(fromCurrency)) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Specified 'from' currency not supported in this JVM: " + fromCurrency);
          }
          if (null == CurrencyField.getCurrency(toCurrency)) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Specified 'to' currency not supported in this JVM: " + toCurrency);
          }
          
          try {
            exchangeRate = Double.parseDouble(rate.getNodeValue());
          } catch (NumberFormatException e) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Could not parse exchange rate: " + rateNode, e);
          }
          
          addRate(tmpRates, fromCurrency, toCurrency, exchangeRate);
        }
      } catch (SAXException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
      } catch (IOException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
      } catch (ParserConfigurationException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
      } catch (XPathExpressionException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
      }
    } catch (IOException e) {
      throw new SolrException(ErrorCode.SERVER_ERROR, "Error while opening Currency configuration file "+currencyConfigFile, e);
    } finally {
      try {
        if (is != null) {
          is.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    // Atomically swap in the new rates map, if it loaded successfully
    this.rates = tmpRates;
    return true;
  }

  @Override
  public void init(Map<String,String> params) throws SolrException {
    this.currencyConfigFile = params.get(PARAM_CURRENCY_CONFIG);
    if(currencyConfigFile == null) {
      throw new SolrException(ErrorCode.NOT_FOUND, "Missing required configuration "+PARAM_CURRENCY_CONFIG);
    }
    
    // Removing config params custom to us
    params.remove(PARAM_CURRENCY_CONFIG);
  }

  @Override
  public void inform(ResourceLoader loader) throws SolrException {
    if(loader == null) {
      throw new SolrException(ErrorCode.SERVER_ERROR, "Needs ResourceLoader in order to load config file");
    }
    this.loader = loader;
    reload();
  }
}

/**
 * Represents a Currency field value, which includes a long amount and ISO currency code.
 */
class CurrencyValue {
  private long amount;
  private String currencyCode;

  /**
   * Constructs a new currency value.
   *
   * @param amount       The amount.
   * @param currencyCode The currency code.
   */
  public CurrencyValue(long amount, String currencyCode) {
    this.amount = amount;
    this.currencyCode = currencyCode;
  }

  /**
   * Constructs a new currency value by parsing the specific input.
   * <p/>
   * Currency values are expected to be in the format &lt;amount&gt;,&lt;currency code&gt;,
   * for example, "500,USD" would represent 5 U.S. Dollars.
   * <p/>
   * If no currency code is specified, the default is assumed.
   *
   * @param externalVal The value to parse.
   * @param defaultCurrency The default currency.
   * @return The parsed CurrencyValue.
   */
  public static CurrencyValue parse(String externalVal, String defaultCurrency) {
    if (externalVal == null) {
      return null;
    }
    String amount = externalVal;
    String code = defaultCurrency;

    if (externalVal.contains(",")) {
      String[] amountAndCode = externalVal.split(",");
      amount = amountAndCode[0];
      code = amountAndCode[1];
    }

    if (amount.equals("*")) {
      return null;
    }
    
    Currency currency = CurrencyField.getCurrency(code);

    if (currency == null) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + code);
    }

    try {
      double value = Double.parseDouble(amount);
      long currencyValue = Math.round(value * Math.pow(10.0, currency.getDefaultFractionDigits()));

      return new CurrencyValue(currencyValue, code);
    } catch (NumberFormatException e) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
    }
  }

  /**
   * The amount of the CurrencyValue.
   *
   * @return The amount.
   */
  public long getAmount() {
    return amount;
  }

  /**
   * The ISO currency code of the CurrencyValue.
   *
   * @return The currency code.
   */
  public String getCurrencyCode() {
    return currencyCode;
  }

  /**
   * Performs a currency conversion & unit conversion.
   *
   * @param exchangeRates      Exchange rates to apply.
   * @param sourceCurrencyCode The source currency code.
   * @param sourceAmount       The source amount.
   * @param targetCurrencyCode The target currency code.
   * @return The converted indexable units after the exchange rate and currency fraction digits are applied.
   */
  public static long convertAmount(ExchangeRateProvider exchangeRates, String sourceCurrencyCode, long sourceAmount, String targetCurrencyCode) {
    double exchangeRate = exchangeRates.getExchangeRate(sourceCurrencyCode, targetCurrencyCode);
    return convertAmount(exchangeRate, sourceCurrencyCode, sourceAmount, targetCurrencyCode);
  }

  /**
   * Performs a currency conversion & unit conversion.
   *
   * @param exchangeRate         Exchange rate to apply.
   * @param sourceFractionDigits The fraction digits of the source.
   * @param sourceAmount         The source amount.
   * @param targetFractionDigits The fraction digits of the target.
   * @return The converted indexable units after the exchange rate and currency fraction digits are applied.
   */
  public static long convertAmount(final double exchangeRate, final int sourceFractionDigits, final long sourceAmount, final int targetFractionDigits) {
    int digitDelta = targetFractionDigits - sourceFractionDigits;
    double value = ((double) sourceAmount * exchangeRate);

    if (digitDelta != 0) {
      if (digitDelta < 0) {
        for (int i = 0; i < -digitDelta; i++) {
          value *= 0.1;
        }
      } else {
        for (int i = 0; i < digitDelta; i++) {
          value *= 10.0;
        }
      }
    }

    return (long) value;
  }

  /**
   * Performs a currency conversion & unit conversion.
   *
   * @param exchangeRate       Exchange rate to apply.
   * @param sourceCurrencyCode The source currency code.
   * @param sourceAmount       The source amount.
   * @param targetCurrencyCode The target currency code.
   * @return The converted indexable units after the exchange rate and currency fraction digits are applied.
   */
  public static long convertAmount(double exchangeRate, String sourceCurrencyCode, long sourceAmount, String targetCurrencyCode) {
    if (targetCurrencyCode.equals(sourceCurrencyCode)) {
      return sourceAmount;
    }

    int sourceFractionDigits = Currency.getInstance(sourceCurrencyCode).getDefaultFractionDigits();
    Currency targetCurrency = Currency.getInstance(targetCurrencyCode);
    int targetFractionDigits = targetCurrency.getDefaultFractionDigits();
    return convertAmount(exchangeRate, sourceFractionDigits, sourceAmount, targetFractionDigits);
  }

  /**
   * Returns a new CurrencyValue that is the conversion of this CurrencyValue to the specified currency.
   *
   * @param exchangeRates      The exchange rate provider.
   * @param targetCurrencyCode The target currency code to convert this CurrencyValue to.
   * @return The converted CurrencyValue.
   */
  public CurrencyValue convertTo(ExchangeRateProvider exchangeRates, String targetCurrencyCode) {
    return new CurrencyValue(convertAmount(exchangeRates, this.getCurrencyCode(), this.getAmount(), targetCurrencyCode), targetCurrencyCode);
  }

  @Override
  public String toString() {
    return String.valueOf(amount) + "," + currencyCode;
  }
}
