/********************************************************************************
 * Copyright (c) 2025-2026 ZF Friedrichshafen AG
 *
 * This program and the accompanying materials are made available under the
 * terms of the Apache License Version 2.0 which is available at
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contributors:
 *   Erik Verhoeven - initial API and implementation
 ********************************************************************************/

#include "path_match_test_suite.h"
#include "../../../global/path_match.h"
#include "../../../global/exec_dir_helper.h"

using CWildcardPathMatchTest = CPathMatchTest;

TEST_F(CWildcardPathMatchTest, DirectFile)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir1/file10.bin").size(), 1); // Match exactly "subdir1/file10.bin"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_xyz/subdir4/subdir5/file50a.bin").size(), 1); // Match exactly "subdir3_xyz/subdir4/subdir5/file50a.bin"
}


TEST_F(CWildcardPathMatchTest, DirectDir)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir2").size(), 3); // Match all files of the "subdir2" directory
}

TEST_F(CWildcardPathMatchTest, DoubleAsterisk_Wildcard)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "**").size(), 10); // Match all files of all directories
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/file50a.bin").size(), 1); // Match "file50a.bin" in any directory
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_xyz/**").size(), 5); // Match all files in subdir3_xyz directory and any directory underneath
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_xyz/**/file50a.bin").size(), 1); // Match "file50a.bin" in subdir3_xyz directory and any directory underneath
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/subdir1").size(), 2); // Match all files in any directory with the name "subdir1"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/subdir4/*").size(), 1); // match all files in any directory with the name "subdir5" underneath any directory with the name "subdir3_xyz"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/subdir3_xyz/**/subdir5/*").size(), 1); // Match all files in any directory with the name "subdir5" underneath any directory with the name "subdir3_xyz"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_xyz/**/subdir4/**/subdir5/*").size(), 1); // Match all files in the directory with the name "subdir5" underneath any directory with the name "subdir4" underneath the directory with the name "subdir3_xyz"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/subdir*").size(), 10); // Match all files in any directory (as well as subdirectories) starting with the name "subdir"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/subdir5").size(), 1); // Match all files in any directory or subdirectory with the name "subdir5"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/subdir4*").size(), 1); // Match all files in any directory (as well as subdirectories) starting with the name "subdir4"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/file4*").size(), 1); // Match all files starting with the name "file4" in any directory (as well as subdirectories)
}

TEST_F(CWildcardPathMatchTest, File_Asterisk_Wildcard)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir1/*").size(), 2); // Match all files in the "subdir1" directory
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir1/*.*").size(), 2); // Match all files with any filename and any extension in the "subdir1" directory
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir2/*2*.*").size(), 3); // Match all files with any filename having "2" in the name and any extension in the "subdir2" directory
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_xyz/file*").size(), 3); // Match all files in the "subdir3_xyz" directory (but not subdirectory) starting with "file" in its filename
    EXPECT_EQ(CollectWildcardPath(rpathBase, "*/*").size(), 8); // Match all files in any top directory (but not from the subdirectories)
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_xyz/*").size(), 3); // Match all files in "subdir3_xyz" (but not from the subdirectories)
}

TEST_F(CWildcardPathMatchTest, Dir_Asterisk_Wildcard)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir*").size(), 8); // Match all files in the top directory starting with "subdir" (but not from the subdirectories)
}

TEST_F(CWildcardPathMatchTest, File_QuestionMark_Wildcard)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir2/file2?.bin").size(), 2); // Match all files in "subdir2" starting with the filename "file2" followed by an alpha-numerical character and ending with the extension "bin"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir1/file1?.bin").size(), 2); // Match all files in "subdir1" starting with the filename "file1" followed by an alpha-numerical character and ending with the extension "bin"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir2/file2?.b??").size(), 3); // Match all files in "subdir2" starting with the filename "file2" followed by an alpha-numerical character and an extension starting with "b" followed by two alpha-numerical characters
}

TEST_F(CWildcardPathMatchTest, Dir_QuestionMark_Wildcard)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir?").size(), 5); // Match all files from the directory starting with "subdir" followed by an alpha-numerical character (but not from the sub-directories)
}

TEST_F(CWildcardPathMatchTest, Combination_Wildcards)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir?_xyz/*").size(), 3); // Match all files with any name from the directory starting with "subdir" followed by an alpha-numerical character and followed by "*xyz"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/file??a.*").size(), 3); // Match all files in any of the directories starting with "file" followed by two alpha-numerical characters followed by "a" with any extension
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir3_*/**/*50*.*").size(), 1); // Match all files having "50" in its file name with any extension in the directory starting with "subdir3*" followed by any text or in any of its subdirectories
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir?/*").size(), 5); // Match all files having any name in the directory starting with "subdir" followed by an alpha-numerical character (but not from the sub-directories)
}

TEST_F(CWildcardPathMatchTest, Extension_Wildcards)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/*.bin").size(), 8); // Match all files in any directory with any name having the extension "bin"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/*.bia").size(), 2); // Match all files in any directory with any name having the extension "bia"
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir*/*.bin").size(), 6); // Match all files in the directory starting with "subdir" followed by any text (but not from the subdirectories) having the extension "bin"
}

TEST_F(CWildcardPathMatchTest, NoMatch)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir1/file1").size(), 0); // Match exactly "subdir1/file1" (which doesn't exist)
    EXPECT_EQ(CollectWildcardPath(rpathBase, "nonexistent/*").size(), 0); // Match all files with any name in the directory "nonexistent" (which do not exist)
    EXPECT_EQ(CollectWildcardPath(rpathBase, "*").size(), 0); // Match all files with any name in the root directory (which do not exist)
    EXPECT_EQ(CollectWildcardPath(rpathBase, "subdir1/file10.bia").size(), 0); // Match exactly "subdir1/file10.bia" (which do not exist)
}

TEST_F(CWildcardPathMatchTest, Navigation_Pattern)
{
    std::filesystem::path rpathBase = GetExecDirectory() / "path_match_test";

    // Current and higher directory in pattern
    EXPECT_EQ(CollectWildcardPath(rpathBase, "./**/file50a.bin").size(), 1); // Match "file50a.bin" in the "." directory or any of its sub-directories
    EXPECT_EQ(CollectWildcardPath(rpathBase, "../**/file50a.bin").size(), 1); // Match "file50a.bin" in the ".." directory or any of its sub-directories
    EXPECT_EQ(CollectWildcardPath(rpathBase, "../*/subdir1/file10.bin").size(), 1); // Match "subdir1/file10.bin" in any directory following the ".." directory (but not from the subdirectories)
    EXPECT_EQ(CollectWildcardPath(rpathBase, "*/../subdir1/file10.bin").size(), 1); // Match "subdir1/file10.bin" in the parent directory ".." of any top directory (but not from the subdirectories)
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/../subdir5/file50a.bin").size(), 1); // Match "subdir5/file50a.bin" in the parent directory ".." of any diretory or subdirectory
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/../../subdir5/file50a.bin").size(), 1); // Match "subdir5/file50a.bin" in the parent directory ".." of the parent directory ".." of any directory or subdirectory
    EXPECT_EQ(CollectWildcardPath(rpathBase, "**/../../subdir1/file10.bin").size(), 0); // Match "subdir1/file10.bin" in the parent directory ".." of the parent directory ".." of any directory or subdirectory (which do not exist)
}