/*
 * 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.kafka.appender;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.categories.Appenders;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
import org.apache.logging.log4j.junit.LoggerContextRule;
import org.apache.logging.log4j.kafka.appender.KafkaManager;
import org.apache.logging.log4j.kafka.appender.KafkaProducerFactory;
import org.apache.logging.log4j.message.SimpleMessage;
import org.apache.logging.log4j.util.FilteredObjectInputStream;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import static org.junit.Assert.*;

@Category(Appenders.Kafka.class)
public class KafkaAppenderTest {

    private static final MockProducer<byte[], byte[]> kafka = new MockProducer<byte[], byte[]>(true, null, null) {

        @Override
        public void close(final long timeout, final TimeUnit timeUnit) {
        }

    };

    private static final String LOG_MESSAGE = "Hello, world!";
    private static final String TOPIC_NAME = "kafka-topic";

    private static Log4jLogEvent createLogEvent() {
        return Log4jLogEvent.newBuilder()
            .setLoggerName(KafkaAppenderTest.class.getName())
            .setLoggerFqcn(KafkaAppenderTest.class.getName())
            .setLevel(Level.INFO)
            .setMessage(new SimpleMessage(LOG_MESSAGE))
            .build();
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
        KafkaManager.producerFactory = new KafkaProducerFactory() {
            @Override
            public Producer<byte[], byte[]> newKafkaProducer(final Properties config) {
                return kafka;
            }
        };
    }

    @Rule
    public LoggerContextRule ctx = new LoggerContextRule("KafkaAppenderTest.xml");

    @Before
    public void setUp() throws Exception {
        kafka.clear();
    }

    @Test
    public void testAppendWithLayout() throws Exception {
        final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithLayout");
        appender.append(createLogEvent());
        final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
        assertEquals(1, history.size());
        final ProducerRecord<byte[], byte[]> item = history.get(0);
        assertNotNull(item);
        assertEquals(TOPIC_NAME, item.topic());
        assertNull(item.key());
        assertEquals("[" + LOG_MESSAGE + "]", new String(item.value(), StandardCharsets.UTF_8));
    }

    @Test
    public void testAsyncAppend() throws Exception {
        final Appender appender = ctx.getRequiredAppender("AsyncKafkaAppender");
        appender.append(createLogEvent());
        final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
        assertEquals(1, history.size());
        final ProducerRecord<byte[], byte[]> item = history.get(0);
        assertNotNull(item);
        assertEquals(TOPIC_NAME, item.topic());
        assertNull(item.key());
        assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
    }

    @Test
    public void testAppendWithKey() throws Exception {
        final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithKey");
        final LogEvent logEvent = createLogEvent();
        appender.append(logEvent);
        final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
        assertEquals(1, history.size());
        final ProducerRecord<byte[], byte[]> item = history.get(0);
        assertNotNull(item);
        assertEquals(TOPIC_NAME, item.topic());
        byte[] keyValue = "key".getBytes(StandardCharsets.UTF_8);
        assertEquals(Long.valueOf(logEvent.getTimeMillis()), item.timestamp());
        assertArrayEquals(item.key(), keyValue);
        assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
    }

    @Test
    public void testAppendWithKeyLookup() throws Exception {
        final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithKeyLookup");
        final LogEvent logEvent = createLogEvent();
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
        appender.append(logEvent);
        final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
        assertEquals(1, history.size());
        final ProducerRecord<byte[], byte[]> item = history.get(0);
        assertNotNull(item);
        assertEquals(TOPIC_NAME, item.topic());
        byte[] keyValue = format.format(date).getBytes(StandardCharsets.UTF_8);
        assertEquals(Long.valueOf(logEvent.getTimeMillis()), item.timestamp());
        assertArrayEquals(item.key(), keyValue);
        assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
    }


    @Test
    public void testAppenderNoEventTimestamp() throws Exception {
        final Appender appender = ctx.getRequiredAppender("KafkaAppenderNoEventTimestamp");
        final LogEvent logEvent = createLogEvent();
        appender.append(logEvent);
        final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
        assertEquals(1, history.size());
        final ProducerRecord<byte[], byte[]> item = history.get(0);
        assertNotNull(item);
        assertEquals(TOPIC_NAME, item.topic());
        byte[] keyValue = "key".getBytes(StandardCharsets.UTF_8);
        assertArrayEquals(item.key(), keyValue);
        assertNotEquals(Long.valueOf(logEvent.getTimeMillis()), item.timestamp());
        assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
    }

    private LogEvent deserializeLogEvent(final byte[] data) throws IOException, ClassNotFoundException {
        final ByteArrayInputStream bis = new ByteArrayInputStream(data);
        try (ObjectInput ois = new FilteredObjectInputStream(bis)) {
            return (LogEvent) ois.readObject();
        }
    }

}
