/*
 * 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.logging.log4j.layout.template.json.resolver;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.time.Instant;
import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
import org.apache.logging.log4j.layout.template.json.util.InstantFormatter;
import org.apache.logging.log4j.layout.template.json.util.JsonWriter;

import java.util.Locale;
import java.util.TimeZone;

/**
 * Timestamp resolver.
 *
 * <h3>Configuration</h3>
 *
 * <pre>
 * config        = [ patternConfig | epochConfig ]
 *
 * patternConfig = "pattern" -> ( [ format ] , [ timeZone ] , [ locale ] )
 * format        = "format" -> string
 * timeZone      = "timeZone" -> string
 * locale        = "locale" -> (
 *                     language                                   |
 *                   ( language , "_" , country )                 |
 *                   ( language , "_" , country , "_" , variant )
 *                 )
 *
 * epochConfig   = "epoch" -> ( unit , [ rounded ] )
 * unit          = "unit" -> (
 *                     "nanos"         |
 *                     "millis"        |
 *                     "secs"          |
 *                     "millis.nanos"  |
 *                     "secs.nanos"    |
 *                  )
 * rounded       = "rounded" -> boolean
 * </pre>
 *
 * If no configuration options are provided, <tt>pattern-config</tt> is
 * employed. There {@link
 * JsonTemplateLayoutDefaults#getTimestampFormatPattern()}, {@link
 * JsonTemplateLayoutDefaults#getTimeZone()}, {@link
 * JsonTemplateLayoutDefaults#getLocale()} are used as defaults for
 * <tt>pattern</tt>, <tt>timeZone</tt>, and <tt>locale</tt>, respectively.
 *
 * In <tt>epoch-config</tt>, <tt>millis.nanos</tt>, <tt>secs.nanos</tt> stand
 * for the fractional component in nanoseconds.
 *
 * <h3>Examples</h3>
 *
 * <table>
 * <tr>
 *     <td>Configuration</td>
 *     <td>Output</td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp"
 * }
 *     </pre></td>
 *     <td><pre>
 * 2020-02-07T13:38:47.098+02:00
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "pattern": {
 *     "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
 *     "timeZone": "UTC",
 *     "locale": "en_US"
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 * 2020-02-07T13:38:47.098Z
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "secs"
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 * 1581082727.982123456
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "secs",
 *     "rounded": true
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 * 1581082727
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "secs.nanos"
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 *            982123456
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "millis"
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 * 1581082727982.123456
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "millis",
 *     "rounded": true
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 * 1581082727982
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "millis.nanos"
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 *              123456
 *     </pre></td>
 * </tr>
 * <tr>
 *     <td><pre>
 * {
 *   "$resolver": "timestamp",
 *   "epoch": {
 *     "unit": "nanos"
 *   }
 * }
 *     </pre></td>
 *     <td><pre>
 * 1581082727982123456
 *     </pre></td>
 * </tr>
 * </table>
 */
public final class TimestampResolver implements EventResolver {

    private final EventResolver internalResolver;

    TimestampResolver(final TemplateResolverConfig config) {
        this.internalResolver = createResolver(config);
    }

    private static EventResolver createResolver(
            final TemplateResolverConfig config) {
        final boolean patternProvided = config.exists("pattern");
        final boolean epochProvided = config.exists("epoch");
        if (patternProvided && epochProvided) {
            throw new IllegalArgumentException(
                    "conflicting configuration options are provided: " + config);
        }
        return epochProvided
                ? createEpochResolver(config)
                : createPatternResolver(config);
    }

    private static final class PatternResolverContext {

        private final InstantFormatter formatter;

        private final StringBuilder lastFormattedInstantBuffer = new StringBuilder();

        private Instant lastFormattedInstant;

        private PatternResolverContext(
                final String pattern,
                final TimeZone timeZone,
                final Locale locale) {
            this.formatter = InstantFormatter
                    .newBuilder()
                    .setPattern(pattern)
                    .setTimeZone(timeZone)
                    .setLocale(locale)
                    .build();
        }

        private static PatternResolverContext fromConfig(
                final TemplateResolverConfig config) {
            final String pattern = readPattern(config);
            final TimeZone timeZone = readTimeZone(config);
            final Locale locale = config.getLocale(new String[]{"pattern", "locale"});
            return new PatternResolverContext(pattern, timeZone, locale);
        }

        private static String readPattern(final TemplateResolverConfig config) {
            final String format = config.getString(new String[]{"pattern", "format"});
            return format != null
                    ? format
                    : JsonTemplateLayoutDefaults.getTimestampFormatPattern();
        }

        private static TimeZone readTimeZone(final TemplateResolverConfig config) {
            final String timeZoneId = config.getString(new String[]{"pattern", "timeZone"});
            if (timeZoneId == null) {
                return JsonTemplateLayoutDefaults.getTimeZone();
            }
            boolean found = false;
            for (final String availableTimeZone : TimeZone.getAvailableIDs()) {
                if (availableTimeZone.equalsIgnoreCase(timeZoneId)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new IllegalArgumentException(
                        "invalid timestamp time zone: " + config);
            }
            return TimeZone.getTimeZone(timeZoneId);
        }

    }

    private static final class PatternResolver implements EventResolver {

        private final PatternResolverContext patternResolverContext;

        private PatternResolver(final PatternResolverContext patternResolverContext) {
            this.patternResolverContext = patternResolverContext;
        }

        @Override
        public synchronized void resolve(
                final LogEvent logEvent,
                final JsonWriter jsonWriter) {

            // Format timestamp if it doesn't match the last cached one.
            if (patternResolverContext.lastFormattedInstant == null ||
                    !patternResolverContext.formatter.isInstantMatching(
                            patternResolverContext.lastFormattedInstant,
                            logEvent.getInstant())) {

                // Format the timestamp.
                patternResolverContext.lastFormattedInstantBuffer.setLength(0);
                patternResolverContext.lastFormattedInstant = logEvent.getInstant();
                patternResolverContext.formatter.format(
                        patternResolverContext.lastFormattedInstant,
                        patternResolverContext.lastFormattedInstantBuffer);

                // Write the formatted timestamp.
                final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
                final int startIndex = jsonWriterStringBuilder.length();
                jsonWriter.writeString(patternResolverContext.lastFormattedInstantBuffer);

                // Cache the written value.
                patternResolverContext.lastFormattedInstantBuffer.setLength(0);
                patternResolverContext.lastFormattedInstantBuffer.append(
                        jsonWriterStringBuilder,
                        startIndex,
                        jsonWriterStringBuilder.length());

            }

            // Write the cached formatted timestamp.
            else {
                jsonWriter.writeRawString(
                        patternResolverContext.lastFormattedInstantBuffer);
            }

        }

    }

    private static EventResolver createPatternResolver(
            final TemplateResolverConfig config) {
        final PatternResolverContext patternResolverContext =
                PatternResolverContext.fromConfig(config);
        return new PatternResolver(patternResolverContext);
    }

    private static EventResolver createEpochResolver(
            final TemplateResolverConfig config) {
        final String unit = config.getString(new String[]{"epoch", "unit"});
        final Boolean rounded = config.getBoolean(new String[]{"epoch", "rounded"});
        if ("nanos".equals(unit) && !Boolean.FALSE.equals(rounded)) {
            return EPOCH_NANOS_RESOLVER;
        } else if ("millis".equals(unit)) {
            return !Boolean.TRUE.equals(rounded)
                    ? EPOCH_MILLIS_RESOLVER
                    : EPOCH_MILLIS_ROUNDED_RESOLVER;
        } else if ("millis.nanos".equals(unit) && rounded == null) {
                return EPOCH_MILLIS_NANOS_RESOLVER;
        } else if ("secs".equals(unit)) {
            return !Boolean.TRUE.equals(rounded)
                    ? EPOCH_SECS_RESOLVER
                    : EPOCH_SECS_ROUNDED_RESOLVER;
        } else if ("secs.nanos".equals(unit) && rounded == null) {
            return EPOCH_SECS_NANOS_RESOLVER;
        }
        throw new IllegalArgumentException(
                "invalid epoch configuration: " + config);
    }

    private static final class EpochResolutionRecord {

        private static final int MAX_LONG_LENGTH =
                String.valueOf(Long.MAX_VALUE).length();

        private Instant instant;

        private final char[] resolution = new char[
                /* integral: */ MAX_LONG_LENGTH +
                /* dot: */ 1 +
                /* fractional: */ MAX_LONG_LENGTH];

        private int resolutionLength;

        private EpochResolutionRecord() {}

    }

    private static abstract class EpochResolver implements EventResolver {

        private final EpochResolutionRecord resolutionRecord =
                new EpochResolutionRecord();

        @Override
        public synchronized void resolve(
                final LogEvent logEvent,
                final JsonWriter jsonWriter) {
            final Instant logEventInstant = logEvent.getInstant();
            if (logEventInstant.equals(resolutionRecord.instant)) {
                jsonWriter.writeRawString(
                        resolutionRecord.resolution,
                        0,
                        resolutionRecord.resolutionLength);
            } else {
                resolutionRecord.instant = logEventInstant;
                final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
                final int startIndex = stringBuilder.length();
                resolve(logEventInstant, jsonWriter);
                resolutionRecord.resolutionLength = stringBuilder.length() - startIndex;
                stringBuilder.getChars(
                        startIndex,
                        stringBuilder.length(),
                        resolutionRecord.resolution,
                        0);
            }
        }

        abstract void resolve(Instant logEventInstant, JsonWriter jsonWriter);

    }

    private static final EventResolver EPOCH_NANOS_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    final long nanos = epochNanos(logEventInstant);
                    jsonWriter.writeNumber(nanos);
                }
            };

    private static final EventResolver EPOCH_MILLIS_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
                    final long nanos = epochNanos(logEventInstant);
                    jsonWriterStringBuilder.append(nanos);
                    jsonWriterStringBuilder.insert(jsonWriterStringBuilder.length() - 6, '.');
                }
            };

    private static final EventResolver EPOCH_MILLIS_ROUNDED_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    jsonWriter.writeNumber(logEventInstant.getEpochMillisecond());
                }
            };

    private static final EventResolver EPOCH_MILLIS_NANOS_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    final long nanos = epochNanos(logEventInstant);
                    final long fraction = nanos % 1_000_000L;
                    jsonWriter.writeNumber(fraction);
                }
            };

    private static final EventResolver EPOCH_SECS_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
                    final long nanos = epochNanos(logEventInstant);
                    jsonWriterStringBuilder.append(nanos);
                    jsonWriterStringBuilder.insert(jsonWriterStringBuilder.length() - 9, '.');
                }
            };

    private static final EventResolver EPOCH_SECS_ROUNDED_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    jsonWriter.writeNumber(logEventInstant.getEpochSecond());
                }
            };

    private static final EventResolver EPOCH_SECS_NANOS_RESOLVER =
            new EpochResolver() {
                @Override
                void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
                    jsonWriter.writeNumber(logEventInstant.getNanoOfSecond());
                }
            };

    private static long epochNanos(final Instant instant) {
        return 1_000_000_000L * instant.getEpochSecond() + instant.getNanoOfSecond();
    }

    static String getName() {
        return "timestamp";
    }

    @Override
    public void resolve(
            final LogEvent logEvent,
            final JsonWriter jsonWriter) {
        internalResolver.resolve(logEvent, jsonWriter);
    }

}
