// --------------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/sharg-parser/blob/main/LICENSE.md
// --------------------------------------------------------------------------------------------------------

#include <gtest/gtest.h>

#include <sharg/parser.hpp>

TEST(html_format, empty_information)
{
    std::string my_stdout;
    std::string expected;

    // Empty html help page.
    char const * argv0[] = {"./help_add_test --version-check false", "--export-help", "html"};
    sharg::parser parser0{"empty_options", 3, argv0};
    testing::internal::CaptureStdout();
    EXPECT_EXIT(parser0.parse(), ::testing::ExitedWithCode(EXIT_SUCCESS), "");
    my_stdout = testing::internal::GetCapturedStdout();
    expected =
        std::string("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" http://www.w3.org/TR/html4/strict.dtd\">\n"
                    "<html lang=\"en\">\n"
                    "<head>\n"
                    "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"
                    "<title>empty_options &mdash; </title>\n"
                    "</head>\n"
                    "<body>\n"
                    "<h1>empty_options</h1>\n"
                    "<div></div>\n"
                    "<h2>Options</h2>\n"
                    "<h3>Basic options:</h3>\n"
                    "<dl>\n"
                    "<dt><strong>-h</strong>, <strong>--help</strong></dt>\n"
                    "<dd>Prints the help page.</dd>\n"
                    "<dt><strong>-hh</strong>, <strong>--advanced-help</strong></dt>\n"
                    "<dd>Prints the help page including advanced options.</dd>\n"
                    "<dt><strong>--version</strong></dt>\n"
                    "<dd>Prints the version information.</dd>\n"
                    "<dt><strong>--copyright</strong></dt>\n"
                    "<dd>Prints the copyright/license information.</dd>\n"
                    "<dt><strong>--export-help</strong> (std::string)</dt>\n"
                    "<dd>Export the help page information. Value must be one of [html, man].</dd>\n"
                    "<dt><strong>--version-check</strong> (bool)</dt>\n"
                    "<dd>Whether to check for the newest app version. Default: true.</dd>\n"
                    "</dl>\n"
                    "<h2>Version</h2>\n"
                    "<p>\n"
                    "<strong>Last update: </strong>\n"
                    "<br>\n"
                    "<strong>empty_options version: </strong>\n"
                    "<br>\n"
                    "<strong>Sharg version: </strong>"
                    + std::string{sharg::sharg_version_cstring}
                    + "\n"
                      "<br>\n"
                      "</p>\n"
                      "</body></html>");
    EXPECT_EQ(my_stdout, expected);

    char const * argv1[] = {"./help_add_test --version-check false", "--export-help=html"};
    sharg::parser parser1{"empty_options", 2, argv1};
    testing::internal::CaptureStdout();
    EXPECT_EXIT(parser1.parse(), ::testing::ExitedWithCode(EXIT_SUCCESS), "");
    my_stdout = testing::internal::GetCapturedStdout();
    EXPECT_EQ(my_stdout, expected);
}

TEST(html_format, full_information_information)
{
    std::string my_stdout;
    std::string expected;
    int option_value{5};
    bool flag_value{false};
    int8_t non_list_pos_opt_value{1};
    std::vector<std::string> list_pos_opt_value{};

    // Full html help page.
    char const * argv0[] = {"./help_add_test --version-check false", "--export-help", "html"};
    sharg::parser parser1{"program_full_options", 3, argv0};
    parser1.info.synopsis.push_back("./some_binary_name synopsis");
    parser1.info.synopsis.push_back("./some_binary_name synopsis2");
    parser1.info.description.push_back("description");
    parser1.info.description.push_back("description2");
    parser1.info.short_description = "short description";
    parser1.info.url = "https://seqan.de";
    parser1.info.short_copyright = "short copyright";
    parser1.info.long_copyright = "long_copyright";
    parser1.info.citation = "citation";
    parser1.info.author = "author";
    parser1.info.email = "email";
    parser1.add_option(option_value,
                       sharg::config{.short_id = 'i',
                                     .long_id = "int",
                                     .description = "this is a int option.",
                                     .default_message = "A number"});
    parser1.add_option(option_value,
                       sharg::config{.short_id = 'j',
                                     .long_id = "jint",
                                     .description = "this is a required int option.",
                                     .required = true});
    parser1.add_flag(flag_value, sharg::config{.short_id = 'f', .long_id = "flag", .description = "this is a flag."});
    parser1.add_flag(flag_value, sharg::config{.short_id = 'k', .long_id = "kflag", .description = "this is a flag."});
    parser1.add_positional_option(non_list_pos_opt_value, sharg::config{.description = "this is a positional option."});
    parser1.add_positional_option(list_pos_opt_value, sharg::config{.description = "this is a positional option."});
    parser1.info.examples.push_back("example");
    parser1.info.examples.push_back("example2");
    testing::internal::CaptureStdout();
    EXPECT_EXIT(parser1.parse(), ::testing::ExitedWithCode(EXIT_SUCCESS), "");

    my_stdout = testing::internal::GetCapturedStdout();
    expected = std::string(
        "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" http://www.w3.org/TR/html4/strict.dtd\">\n"
        "<html lang=\"en\">\n"
        "<head>\n"
        "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"
        "<title>program_full_options &mdash; short description</title>\n"
        "</head>\n"
        "<body>\n"
        "<h1>program_full_options</h1>\n"
        "<div>short description</div>\n"
        "<h2>Synopsis</h2>\n"
        "<p>\n"
        "<strong>./some_binary_name</strong> synopsis\n"
        "<br>\n"
        "<strong>./some_binary_name</strong> synopsis2\n"
        "<br>\n"
        "</p>\n"
        "<h2>Description</h2>\n"
        "<p>\n"
        "description\n"
        "</p>\n"
        "<p>\n"
        "description2\n"
        "</p>\n"
        "<h2>Positional Arguments</h2>\n"
        "<dl>\n"
        "<dt><strong>ARGUMENT-1</strong> (<em>signed 8 bit integer</em>)</dt>\n"
        "<dd>this is a positional option. </dd>\n"
        "<dt><strong>ARGUMENT-2</strong> (<em>List</em> of <em>std::string</em>)</dt>\n"
        "<dd>this is a positional option. Default: []. </dd>\n"
        "</dl>\n"
        "<h2>Options</h2>\n"
        "<h3>Basic options:</h3>\n"
        "<dl>\n"
        "<dt><strong>-h</strong>, <strong>--help</strong></dt>\n"
        "<dd>Prints the help page.</dd>\n"
        "<dt><strong>-hh</strong>, <strong>--advanced-help</strong></dt>\n"
        "<dd>Prints the help page including advanced options.</dd>\n"
        "<dt><strong>--version</strong></dt>\n"
        "<dd>Prints the version information.</dd>\n"
        "<dt><strong>--copyright</strong></dt>\n"
        "<dd>Prints the copyright/license information.</dd>\n"
        "<dt><strong>--export-help</strong> (std::string)</dt>\n"
        "<dd>Export the help page information. Value must be one of [html, man].</dd>\n"
        "<dt><strong>--version-check</strong> (bool)</dt>\n"
        "<dd>Whether to check for the newest app version. Default: true.</dd>\n"
        "<dt><strong>-i</strong>, <strong>--int</strong> (<em>signed 32 bit integer</em>)</dt>\n"
        "<dd>this is a int option. Default: A number. </dd>\n"
        "<dt><strong>-j</strong>, <strong>--jint</strong> (<em>signed 32 bit integer</em>)</dt>\n"
        "<dd>this is a required int option. </dd>\n"
        "<dt><strong>-f</strong>, <strong>--flag</strong></dt>\n"
        "<dd>this is a flag.</dd>\n"
        "<dt><strong>-k</strong>, <strong>--kflag</strong></dt>\n"
        "<dd>this is a flag.</dd>\n"
        "</dl>\n"
        "<h2>Examples</h2>\n"
        "<p>\n"
        "example\n"
        "</p>\n"
        "<p>\n"
        "example2\n"
        "</p>\n"
        "<h2>Version</h2>\n"
        "<p>\n"
        "<strong>Last update: </strong>\n"
        "<br>\n"
        "<strong>program_full_options version: </strong>\n"
        "<br>\n"
        "<strong>Sharg version: </strong>"
        + std::string{sharg::sharg_version_cstring}
        + "\n"
          "<br>\n"
          "</p>\n"
          "<h2>Url</h2>\n"
          "<p>\n"
          "https://seqan.de\n"
          "<br>\n"
          "</p>\n"
          "<h2>Legal</h2>\n"
          "<p>\n"
          "<strong>program_full_options Copyright: </strong>short copyright\n"
          "<br>\n"
          "<strong>Author: </strong>author\n"
          "<br>\n"
          "<strong>Contact: </strong>email\n"
          "<br>\n"
          "<strong>SeqAn Copyright: </strong>2006-2022 Knut Reinert, FU-Berlin; released under the 3-clause BSDL.\n"
          "<br>\n"
          "<strong>In your academic works please cite: </strong>citation\n"
          "<br>\n"
          "For full copyright and/or warranty information see <strong>--copyright</strong>.\n"
          "<br>\n"
          "</p>\n"
          "</body></html>");
    EXPECT_EQ(my_stdout, expected);
}

TEST(export_help, parse_error)
{
    char const * argv[] = {"./help_add_test --version-check false", "--export-help"};
    char const * argv2[] = {"./help_add_test --version-check false", "--export-help=atml"};
    char const * argv3[] = {"./help_add_test --version-check false", "--export-help", "atml"};

    // no value after --export-help
    EXPECT_THROW((sharg::parser{"test_parser", 2, argv}), sharg::parser_error);

    // wrong value after --export-help
    EXPECT_THROW((sharg::parser{"test_parser", 2, argv2}), sharg::validation_error);

    // wrong value after --export-help
    EXPECT_THROW((sharg::parser{"test_parser", 3, argv3}), sharg::validation_error);
}
