/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

package org.elasticsearch.gradle.docker;

import org.elasticsearch.gradle.test.GradleUnitTestCase;

import java.util.Arrays;
import java.util.List;

import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.hamcrest.Matchers.equalTo;

public class TransformLog4jConfigFilterTests extends GradleUnitTestCase {

    /**
     * Check that the transformer doesn't explode when given an empty file.
     */
    public void testTransformEmptyConfig() {
        runTest(emptyList(), emptyList());
    }

    /**
     * Check that the transformer leaves non-appender lines alone.
     */
    public void testTransformEchoesNonAppenderLines() {
        List<String> input = Arrays.asList(
            "status = error",
            "",
            "##############################",
            "rootLogger.level = info",
            "example = \"broken\\",
            "    line\""
        );

        runTest(input, input);
    }

    /**
     * Check that the root logger appenders are filtered to just the "rolling" appender
     */
    public void testTransformFiltersRootLogger() {
        List<String> input = Arrays.asList(
            "rootLogger.appenderRef.console.ref = console",
            "rootLogger.appenderRef.rolling.ref = rolling",
            "rootLogger.appenderRef.rolling_old.ref = rolling_old"
        );
        List<String> expected = singletonList("rootLogger.appenderRef.rolling.ref = rolling");

        runTest(input, expected);
    }

    /**
     * Check that any explicit 'console' or 'rolling_old' appenders are removed.
     */
    public void testTransformRemoveExplicitConsoleAndRollingOldAppenders() {
        List<String> input = Arrays.asList(
            "appender.console.type = Console",
            "appender.console.name = console",
            "appender.console.layout.type = PatternLayout",
            "appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %m%n",
            "appender.rolling_old.type = RollingFile",
            "appender.rolling_old.name = rolling_old",
            "appender.rolling_old.layout.type = PatternLayout",
            "appender.rolling_old.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %m%n"
        );

        runTest(input, emptyList());
    }

    /**
     * Check that rolling file appenders are converted to console appenders.
     */
    public void testTransformConvertsRollingToConsole() {
        List<String> input = Arrays.asList("appender.rolling.type = RollingFile", "appender.rolling.name = rolling");

        List<String> expected = Arrays.asList("appender.rolling.type = Console", "appender.rolling.name = rolling");

        runTest(input, expected);
    }

    /**
     * Check that rolling file appenders have redundant properties removed.
     */
    public void testTransformRemovedRedundantProperties() {
        List<String> input = Arrays.asList(
            "appender.rolling.fileName = ${sys:es.logs.base_path}/${sys:es.logs.cluster_name}_server.json",
            "appender.rolling.layout.type = ECSJsonLayout",
            "appender.rolling.layout.type_name = server",
            "appender.rolling.filePattern = ${sys:es.logs.base_path}/${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.json.gz",
            "appender.rolling.policies.type = Policies",
            "appender.rolling.strategy.type = DefaultRolloverStrategy"
        );

        List<String> expected = Arrays.asList("appender.rolling.layout.type = ECSJsonLayout", "appender.rolling.layout.type_name = server");

        runTest(input, expected);
    }

    /**
     * Check that rolling file appenders have redundant properties removed.
     */
    public void testTransformSkipsPropertiesWithLineBreaks() {
        List<String> input = Arrays.asList(
            "appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}\\",
            "    ${sys:es.logs.cluster_name}_server.json",
            "appender.rolling.layout.type = ECSJsonLayout"
        );

        List<String> expected = singletonList("appender.rolling.layout.type = ECSJsonLayout");

        runTest(input, expected);
    }

    /**
     * Check that as well as skipping old appenders, logger references to them are also skipped.
     */
    public void testTransformSkipsOldAppenderRefs() {
        List<String> input = singletonList(
            "logger.index_indexing_slowlog.appenderRef.index_indexing_slowlog_rolling_old.ref = index_indexing_slowlog_rolling_old"
        );

        runTest(input, emptyList());
    }

    /**
     * Check that multiple blank lines are reduced to a single line.
     */
    public void testMultipleBlanksReducedToOne() {
        List<String> input = Arrays.asList("status = error", "", "", "rootLogger.level = info");

        List<String> expected = Arrays.asList("status = error", "", "rootLogger.level = info");

        final List<String> transformed = TransformLog4jConfigFilter.skipBlanks(input);
        assertThat(transformed, equalTo(expected));
    }

    private void runTest(List<String> input, List<String> expected) {
        final List<String> transformed = TransformLog4jConfigFilter.transformConfig(input);

        assertThat(transformed, equalTo(expected));
    }
}
