/*
 * 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.
 */

package org.apache.solr.schema;

import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.GeneralField;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.StorableField;
import org.apache.lucene.queries.function.docvalues.DocTermsIndexDocValues;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.FieldCacheSource;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.CharsRef;
import org.apache.lucene.util.UnicodeUtil;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.DateUtil;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.search.QParser;
import org.apache.solr.util.DateMathParser;
import org.apache.solr.update.processor.TimestampUpdateProcessorFactory; //jdoc

import java.io.IOException;
import java.text.*;
import java.util.*;

// TODO: make a FlexibleDateField that can accept dates in multiple
// formats, better for human entered dates.

// TODO: make a DayField that only stores the day?


/**
 * FieldType that can represent any Date/Time with millisecond precision.
 * <p>
 * Date Format for the XML, incoming and outgoing:
 * </p>
 * <blockquote>
 * A date field shall be of the form 1995-12-31T23:59:59Z
 * The trailing "Z" designates UTC time and is mandatory
 * (See below for an explanation of UTC).
 * Optional fractional seconds are allowed, as long as they do not end
 * in a trailing 0 (but any precision beyond milliseconds will be ignored).
 * All other parts are mandatory.
 * </blockquote>
 * <p>
 * This format was derived to be standards compliant (ISO 8601) and is a more
 * restricted form of the
 * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime-canonical-representation">canonical
 * representation of dateTime</a> from XML schema part 2.  Examples...
 * </p>
 * <ul>
 *   <li>1995-12-31T23:59:59Z</li>
 *   <li>1995-12-31T23:59:59.9Z</li>
 *   <li>1995-12-31T23:59:59.99Z</li>
 *   <li>1995-12-31T23:59:59.999Z</li>
 * </ul>
 * <p>
 * Note that DateField is lenient with regards to parsing fractional
 * seconds that end in trailing zeros and will ensure that those values
 * are indexed in the correct canonical format.
 * </p>
 * <p>
 * This FieldType also supports incoming "Date Math" strings for computing
 * values by adding/rounding internals of time relative either an explicit
 * datetime (in the format specified above) or the literal string "NOW",
 * ie: "NOW+1YEAR", "NOW/DAY", "1995-12-31T23:59:59.999Z+5MINUTES", etc...
 * -- see {@link DateMathParser} for more examples.
 * </p>
 * <p>
 * <b>NOTE:</b> Allthough it is possible to configure a <code>DateField</code> 
 * instance with a default value of "<code>NOW</code>" to compute a timestamp 
 * of when the document was indexed, this is not advisable when using SolrCloud 
 * since each replica of the document may compute a slightly different value. 
 * {@link TimestampUpdateProcessorFactory} is recomended instead.
 * </p>
 *
 * <p>
 * Explanation of "UTC"...
 * </p>
 * <blockquote>
 * "In 1970 the Coordinated Universal Time system was devised by an
 * international advisory group of technical experts within the International
 * Telecommunication Union (ITU).  The ITU felt it was best to designate a
 * single abbreviation for use in all languages in order to minimize
 * confusion.  Since unanimous agreement could not be achieved on using
 * either the English word order, CUT, or the French word order, TUC, the
 * acronym UTC was chosen as a compromise."
 * </blockquote>
 *
 *
 * @see <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">XML schema part 2</a>
 * @deprecated {@link TrieDateField} is recomended for all new schemas
 */
public class DateField extends PrimitiveFieldType implements DateValueFieldType {

  public static TimeZone UTC = TimeZone.getTimeZone("UTC");

  /** 
   * No longer used
   * @deprecated use DateMathParser.DEFAULT_MATH_TZ
   * @see DateMathParser#DEFAULT_MATH_TZ
   */
  protected static final TimeZone MATH_TZ = DateMathParser.DEFAULT_MATH_TZ;
  /** 
   * No longer used
   * @deprecated use DateMathParser.DEFAULT_MATH_LOCALE
   * @see DateMathParser#DEFAULT_MATH_LOCALE
   */
  protected static final Locale MATH_LOCALE = DateMathParser.DEFAULT_MATH_LOCALE;

  /** 
   * Fixed TimeZone (UTC) needed for parsing/formating Dates in the 
   * canonical representation.
   */
  protected static final TimeZone CANONICAL_TZ = UTC;
  /** 
   * Fixed Locale needed for parsing/formating Milliseconds in the 
   * canonical representation.
   */
  protected static final Locale CANONICAL_LOCALE = Locale.ROOT;
  
  // The XML (external) date format will sort correctly, except if
  // fractions of seconds are present (because '.' is lower than 'Z').
  // The easiest fix is to simply remove the 'Z' for the internal
  // format.
  
  protected static String NOW = "NOW";
  protected static char Z = 'Z';
  private static char[] Z_ARRAY = new char[] {Z};
  
  
  @Override
  public String toInternal(String val) {
    return toInternal(parseMath(null, val));
  }

  /**
   * Parses a String which may be a date (in the standard format)
   * followed by an optional math expression.
   * @param now an optional fixed date to use as "NOW" in the DateMathParser
   * @param val the string to parse
   */
  public Date parseMath(Date now, String val) {
    String math = null;
    final DateMathParser p = new DateMathParser();
    
    if (null != now) p.setNow(now);
    
    if (val.startsWith(NOW)) {
      math = val.substring(NOW.length());
    } else {
      final int zz = val.indexOf(Z);
      if (0 < zz) {
        math = val.substring(zz+1);
        try {
          // p.setNow(toObject(val.substring(0,zz)));
          p.setNow(parseDate(val.substring(0,zz+1)));
        } catch (ParseException e) {
          throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
                                   "Invalid Date in Date Math String:'"
                                   +val+'\'',e);
        }
      } else {
        throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
                                 "Invalid Date String:'" +val+'\'');
      }
    }

    if (null == math || math.equals("")) {
      return p.getNow();
    }
    
    try {
      return p.parseMath(math);
    } catch (ParseException e) {
      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
                               "Invalid Date Math String:'" +val+'\'',e);
    }
  }

  @Override
  public StorableField createField(SchemaField field, Object value, float boost) {
    // Convert to a string before indexing
    if(value instanceof Date) {
      value = toInternal( (Date)value ) + Z;
    }
    return super.createField(field, value, boost);
  }
  
  public String toInternal(Date val) {
    return formatDate(val);
  }

  @Override
  public String indexedToReadable(String indexedForm) {
    return indexedForm + Z;
  }

  @Override
  public CharsRef indexedToReadable(BytesRef input, CharsRef charsRef) {
    UnicodeUtil.UTF8toUTF16(input, charsRef);
    charsRef.append(Z_ARRAY, 0, 1);
    return charsRef;
  }

  @Override
  public String toExternal(StorableField f) {
    return indexedToReadable(f.stringValue());
  }

  public Date toObject(String indexedForm) throws java.text.ParseException {
    return parseDate(indexedToReadable(indexedForm));
  }

  @Override
  public Date toObject(StorableField f) {
    try {
      return parseDate( toExternal(f) );
    }
    catch( ParseException ex ) {
      throw new RuntimeException( ex );
    }
  }

  @Override
  public SortField getSortField(SchemaField field,boolean reverse) {
    return getStringSort(field,reverse);
  }

  @Override
  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
    writer.writeDate(name, toExternal(f));
  }

  /**
   * Returns a formatter that can be use by the current thread if needed to
   * convert Date objects to the Internal representation.
   *
   * Only the <tt>format(Date)</tt> can be used safely.
   * 
   * @deprecated - use formatDate(Date) instead
   */
  @Deprecated
  protected DateFormat getThreadLocalDateFormat() {
    return fmtThreadLocal.get();
  }

  /**
   * Thread safe method that can be used by subclasses to format a Date
   * using the Internal representation.
   */
  protected String formatDate(Date d) {
    return fmtThreadLocal.get().format(d);
  }

  /**
   * Return the standard human readable form of the date
   */
  public static String formatExternal(Date d) {
    return fmtThreadLocal.get().format(d) + 'Z';
  }

  /**
   * @see #formatExternal
   */
  public String toExternal(Date d) {
    return formatExternal(d);
  }

  /**
   * Thread safe method that can be used by subclasses to parse a Date
   * that is already in the internal representation
   */
   public static Date parseDate(String s) throws ParseException {
     return fmtThreadLocal.get().parse(s);
   }

  /** Parse a date string in the standard format, or any supported by DateUtil.parseDate */
   public Date parseDateLenient(String s, SolrQueryRequest req) throws ParseException {
     // request could define timezone in the future
     try {
       return fmtThreadLocal.get().parse(s);
     } catch (Exception e) {
       return DateUtil.parseDate(s);
     }
   }

  /**
   * Parses a String which may be a date
   * followed by an optional math expression.
   * @param now an optional fixed date to use as "NOW" in the DateMathParser
   * @param val the string to parse
   */
  public Date parseMathLenient(Date now, String val, SolrQueryRequest req) {
    String math = null;
    final DateMathParser p = new DateMathParser();

    if (null != now) p.setNow(now);

    if (val.startsWith(NOW)) {
      math = val.substring(NOW.length());
    } else {
      final int zz = val.indexOf(Z);
      if (0 < zz) {
        math = val.substring(zz+1);
        try {
          // p.setNow(toObject(val.substring(0,zz)));
          p.setNow(parseDateLenient(val.substring(0,zz+1), req));
        } catch (ParseException e) {
          throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
                                   "Invalid Date in Date Math String:'"
                                   +val+'\'',e);
        }
      } else {
        throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
                                 "Invalid Date String:'" +val+'\'');
      }
    }

    if (null == math || math.equals("")) {
      return p.getNow();
    }

    try {
      return p.parseMath(math);
    } catch (ParseException e) {
      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
                               "Invalid Date Math String:'" +val+'\'',e);
    }
  }


  
  /**
   * Thread safe DateFormat that can <b>format</b> in the canonical
   * ISO8601 date format, not including the trailing "Z" (since it is
   * left off in the internal indexed values)
   */
  private final static ThreadLocalDateFormat fmtThreadLocal
    = new ThreadLocalDateFormat(new ISO8601CanonicalDateFormat());
  
  private static class ISO8601CanonicalDateFormat extends SimpleDateFormat {
    
    protected NumberFormat millisParser
      = NumberFormat.getIntegerInstance(CANONICAL_LOCALE);

    protected NumberFormat millisFormat = new DecimalFormat(".###", 
      new DecimalFormatSymbols(CANONICAL_LOCALE));

    public ISO8601CanonicalDateFormat() {
      super("yyyy-MM-dd'T'HH:mm:ss", CANONICAL_LOCALE);
      this.setTimeZone(CANONICAL_TZ);
    }

    @Override
    public Date parse(String i, ParsePosition p) {
      /* delegate to SimpleDateFormat for easy stuff */
      Date d = super.parse(i, p);
      int milliIndex = p.getIndex();
      /* worry about the milliseconds ourselves */
      if (null != d &&
          -1 == p.getErrorIndex() &&
          milliIndex + 1 < i.length() &&
          '.' == i.charAt(milliIndex)) {
        p.setIndex( ++milliIndex ); // NOTE: ++ to chomp '.'
        Number millis = millisParser.parse(i, p);
        if (-1 == p.getErrorIndex()) {
          int endIndex = p.getIndex();
            d = new Date(d.getTime()
                         + (long)(millis.doubleValue() *
                                  Math.pow(10, (3-endIndex+milliIndex))));
        }
      }
      return d;
    }

    @Override
    public StringBuffer format(Date d, StringBuffer toAppendTo,
                               FieldPosition pos) {
      /* delegate to SimpleDateFormat for easy stuff */
      super.format(d, toAppendTo, pos);
      /* worry aboutthe milliseconds ourselves */
      long millis = d.getTime() % 1000l;
      if (0L == millis) {
        return toAppendTo;
      }
      if (millis < 0L) {
        // original date was prior to epoch
        millis += 1000L;
      }
      int posBegin = toAppendTo.length();
      toAppendTo.append(millisFormat.format(millis / 1000d));
      if (DateFormat.MILLISECOND_FIELD == pos.getField()) {
        pos.setBeginIndex(posBegin);
        pos.setEndIndex(toAppendTo.length());
      }
      return toAppendTo;
    }

    @Override
    public DateFormat clone() {
      ISO8601CanonicalDateFormat c
        = (ISO8601CanonicalDateFormat) super.clone();
      c.millisParser = NumberFormat.getIntegerInstance(CANONICAL_LOCALE);
      c.millisFormat = new DecimalFormat(".###", 
        new DecimalFormatSymbols(CANONICAL_LOCALE));
      return c;
    }
  }
  
  private static class ThreadLocalDateFormat extends ThreadLocal<DateFormat> {
    DateFormat proto;
    public ThreadLocalDateFormat(DateFormat d) {
      super();
      proto = d;
    }
    @Override
    protected DateFormat initialValue() {
      return (DateFormat) proto.clone();
    }
  }

  @Override
  public ValueSource getValueSource(SchemaField field, QParser parser) {
    field.checkFieldCacheSource(parser);
    return new DateFieldSource(field.getName(), field);
  }

  /** DateField specific range query */
  public Query getRangeQuery(QParser parser, SchemaField sf, Date part1, Date part2, boolean minInclusive, boolean maxInclusive) {
    return TermRangeQuery.newStringRange(
            sf.getName(),
            part1 == null ? null : toInternal(part1),
            part2 == null ? null : toInternal(part2),
            minInclusive, maxInclusive);
  }

}



class DateFieldSource extends FieldCacheSource {
  // NOTE: this is bad for serialization... but we currently need the fieldType for toInternal()
  SchemaField sf;
  FieldType ft;

  public DateFieldSource(String name, SchemaField sf) {
    super(name);
    this.sf = sf;
    this.ft = sf.getType();
  }

  @Override
  public String description() {
    return "date(" + field + ')';
  }

  @Override
  public FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
    return new DocTermsIndexDocValues(this, readerContext, field) {
      @Override
      protected String toTerm(String readableValue) {
        // needed for frange queries to work properly
        return ft.toInternal(readableValue);
      }

      @Override
      public boolean exists(int doc) {
        return termsIndex.getOrd(doc) >= 0;
      }

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

      @Override
      public int intVal(int doc) {
        int ord=termsIndex.getOrd(doc);
        return ord;
      }

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

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

      @Override
      public String strVal(int doc) {
        int ord=termsIndex.getOrd(doc);
        if (ord == -1) {
          return null;
        } else {
          termsIndex.lookupOrd(ord, spare);
          return ft.indexedToReadable(spare, spareChars).toString();
        }
      }

      @Override
      public Object objectVal(int doc) {
        int ord=termsIndex.getOrd(doc);
        if (ord == -1) {
          return null;
        } else {
          final BytesRef br = new BytesRef();
          termsIndex.lookupOrd(ord, br);
          return ft.toObject(sf, br);
        }
      }

      @Override
      public String toString(int doc) {
        return description() + '=' + intVal(doc);
      }
    };
  }

  @Override
  public boolean equals(Object o) {
    return o instanceof DateFieldSource
            && super.equals(o);
  }

  private static int hcode = DateFieldSource.class.hashCode();
  @Override
  public int hashCode() {
    return hcode + super.hashCode();
  };
}
