/*
 * 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.maven.it;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * An integration test to check the enhancements to print out version
 * information during the reactor summary output at the correct
 * positions.
 *
 * <a href="https://issues.apache.org/jira/browse/MNG-6391">MNG-6391</a>.
 *
 * @author Karl Heinz Marbaise khmarbaise@apache.org
 */
public class MavenITmng6391PrintVersionTest extends AbstractMavenIntegrationTestCase {

    public MavenITmng6391PrintVersionTest() {
        super("[3.6.0,)");
    }

    /**
     * Check that the resulting output is
     * as expected for the root module and last
     * module in build but not for the intermediate
     * modules.
     *
     * @throws Exception in case of failure
     */
    @Test
    public void testitShouldPrintVersionAtTopAndAtBottom() throws Exception {
        File testDir = extractResources("/mng-6391-print-version");

        Verifier verifier = newVerifier(testDir.getAbsolutePath(), false);
        verifier.setAutoclean(false);

        verifier.setLogFileName("version-log.txt");
        verifier.addCliArgument("clean");
        verifier.execute();
        verifier.verifyErrorFreeLog();

        List<String> loadedLines = verifier.loadLines("version-log.txt");
        List<String> resultingLines = extractReactorBuildOrder(loadedLines);

        // We're expecting exactly four lines as result.
        assertEquals(5, resultingLines.size());

        // We expect those lines in the following exact order.
        // Maven 4.0.x has some code new code which takes care of the terminal width to adjust the output.
        // The number of dots can thus vary when running the tests.
        assertTrue(resultingLines.get(0).startsWith("[INFO] Reactor Summary for base-project 1.3.0-SNAPSHOT:"));
        assertTrue(resultingLines.get(1).matches("\\Q[INFO] base-project ............\\E\\.+\\Q SUCCESS [\\E.*"));
        assertTrue(resultingLines.get(2).matches("\\Q[INFO] module-1 ................\\E\\.+\\Q SUCCESS [\\E.*"));
        assertTrue(resultingLines.get(3).matches("\\Q[INFO] module-2 ................\\E\\.+\\Q SUCCESS [\\E.*"));
        assertTrue(resultingLines.get(4).matches("\\Q[INFO] module-3 ................\\E\\.+\\Q SUCCESS [\\E.*"));

        // We expect that line 1..4 have the same length
        int line1Length = resultingLines.get(1).length();
        assertEquals(line1Length, resultingLines.get(2).length());
        assertEquals(line1Length, resultingLines.get(3).length());
        assertEquals(line1Length, resultingLines.get(4).length());
    }

    /**
     * Check that the resulting output is
     * as expected for all modules in case
     * for an aggregator build.
     *
     * @throws Exception in case of failure
     */
    @Test
    public void testitShouldPrintVersionInAllLines() throws Exception {
        File testDir = extractResources("/mng-6391-print-version-aggregator");

        Verifier verifier = newVerifier(testDir.getAbsolutePath(), false);
        verifier.setAutoclean(false);

        verifier.setLogFileName("version-log.txt");
        verifier.addCliArguments("clean");
        verifier.execute();
        verifier.verifyErrorFreeLog();

        List<String> loadedLines = verifier.loadLines("version-log.txt");
        List<String> resultingLines = extractReactorBuildOrder(loadedLines);

        // We're expecting exactly four lines as result.
        assertEquals(5, resultingLines.size());

        // We expect those lines in the following exact order.
        // Maven 4.0.x has some code new code which takes care of the terminal width to adjust the output.
        // The number of dots can thus vary when running the tests.
        assertTrue(resultingLines.get(0).startsWith("[INFO] Reactor Summary:"));
        assertTrue(resultingLines
                .get(1)
                .matches("\\Q[INFO] module-1 1.2.7.43.RELEASE ...............\\E\\.+\\Q SUCCESS [ \\E.*"));
        assertTrue(resultingLines
                .get(2)
                .matches("\\Q[INFO] module-2 7.5-SNAPSHOT ...................\\E\\.+\\Q SUCCESS [ \\E.*"));
        assertTrue(resultingLines
                .get(3)
                .matches("\\Q[INFO] module-3 1-RC1 ..........................\\E\\.+\\Q SUCCESS [ \\E.*"));
        assertTrue(resultingLines
                .get(4)
                .matches("\\Q[INFO] base-project 1.0.0-SNAPSHOT .............\\E\\.+\\Q SUCCESS [ \\E.*"));

        // We expect that line 1..4 have the same length
        int line1Length = resultingLines.get(1).length();
        assertEquals(line1Length, resultingLines.get(2).length());
        assertEquals(line1Length, resultingLines.get(3).length());
        assertEquals(line1Length, resultingLines.get(4).length());
    }

    /**
     * Extract the lines at the end of the Maven output:
     *
     * <pre>
     * [INFO] Reactor Summary..: XXX
     * [INFO]
     * [INFO] ...SUCCESS [  0.035 s]
     * [INFO] ...SUCCESS [  0.035 s]
     * [INFO] ...SUCCESS [  0.035 s]
     * </pre>
     */
    private List<String> extractReactorBuildOrder(List<String> loadedLines) {
        List<String> resultingLines = new LinkedList<>();
        boolean start = false;
        for (String line : loadedLines) {
            if (start) {
                if (line.startsWith("[INFO] -------------")) {
                    start = false;
                } else if (!line.endsWith("[INFO] ")) {
                    resultingLines.add(line);
                }
            } else {
                if (line.startsWith("[INFO] Reactor Summary")) {
                    start = true;
                    resultingLines.add(line);
                }
            }
        }
        return resultingLines;
    }
}
