// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <regex>
#include <unittest/unittest.h>

#include <fidl/flat_ast.h>
#include <fidl/formatter.h>
#include <fidl/lexer.h>
#include <fidl/parser.h>
#include <fidl/source_file.h>
#include <fidl/tree_visitor.h>

#include "examples.h"
#include "test_library.h"

namespace {

std::map<std::string, std::string> formatted_output_;

void InitializeContents() {
    for (auto element : Examples::map()) {
        TestLibrary library(element.first, element.second);
        std::unique_ptr<fidl::raw::File> ast;
        library.Parse(ast);

        fidl::raw::FormattingTreeVisitor visitor;
        visitor.OnFile(ast);

        formatted_output_[element.first] = *visitor.formatted_output();
    }
}

// Tests that repeatedly applying the formatter results in no change.
bool idempotence_test() {
    BEGIN_TEST;

    for (auto element : formatted_output_) {
        TestLibrary library(element.first, element.second);
        std::unique_ptr<fidl::raw::File> ast;
        EXPECT_TRUE(library.Parse(ast));

        fidl::raw::FormattingTreeVisitor visitor;
        visitor.OnFile(ast);

        EXPECT_STR_EQ(element.second.c_str(),
                      visitor.formatted_output()->c_str(), "Applying formatting multiple times produces different results");
    }

    END_TEST;
}

bool basic_formatting_rules_test() {
    BEGIN_TEST;

    std::regex trailing_ws(".*\\s+$");
    std::regex top_level_decl("^\\s*(?:struct|enum|union)\\s+.*");
    std::regex attribute("\\s*\\[[A-Za-z]+\\]\\s*");
    std::regex comment("\\s*//.*");

    // Break the output into lines
    for (auto element : formatted_output_) {
        std::stringstream ss(element.second);
        std::string line;
        std::vector<std::string> lines;

        while (std::getline(ss, line, '\n')) {
            lines.push_back(line);

            // RULE: No trailing whitespace
            ASSERT_FALSE(std::regex_search(line, trailing_ws), "Trailing whitespace found");

            // RULE: No tab characters
            ASSERT_TRUE(line.find_first_of('\t') == std::string::npos, "Tab character found");

            // RULE: 4 space indents (at least)
            ASSERT_TRUE(!isspace(line[0]) || line.find_first_of("    ") == 0, "<4 space indent found");
        }

        // RULE: Separate top-level declarations for struct, enum, and union with one
        // blank line.
        for (size_t i = 0; i < lines.size(); i++) {
            if (std::regex_search(lines[i], top_level_decl)) {
                // Just means there is a top-level decl on the first line.
                if (i == 0) {
                    continue;
                }

                size_t line_to_check = i - 1;
                // Back up to before attributes and comments.
                while (std::regex_search(lines[line_to_check], attribute) ||
                       std::regex_search(lines[line_to_check], comment)) {
                    line_to_check--;
                    ASSERT_GE(line_to_check, 0);
                }

                std::string full = lines[i - 1] + lines[i];
                ASSERT_EQ(lines[line_to_check].size(), 0, "No blank line found before top level decl");
            }
        }

        // RULE: End the file with exactly one newline (no blank lines at the end).
        ASSERT_NE(lines[lines.size() - 1].size(), 0, "No newline at EOF");
    }

    END_TEST;
}

bool golden_file_test() {
    BEGIN_TEST;
    std::string good_output;
    std::string formatted_bad_output;

    for (auto element : Examples::map()) {
        if (element.first.find("testdata/goodformat.test.fidl") != std::string::npos) {
            good_output = Examples::map()[element.first];
        } else if (element.first.find("testdata/badformat.fidl") != std::string::npos) {
            formatted_bad_output = formatted_output_[element.first];
        }
    }

    ASSERT_GT(good_output.size(), 0);
    ASSERT_GT(formatted_bad_output.size(), 0);

    ASSERT_STR_EQ(good_output.c_str(), formatted_bad_output.c_str(), "Formatting for badformat.fidl looks weird");
    END_TEST;
}

} // namespace

BEGIN_TEST_CASE(formatter_tests)
InitializeContents();
RUN_TEST(idempotence_test)
RUN_TEST(basic_formatting_rules_test)
RUN_TEST(golden_file_test)
END_TEST_CASE(formatter_tests)
