/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "bmhParser.h"
#include "selfCheck.h"

#ifdef SK_BUILD_FOR_WIN
#include <windows.h>
#endif


 /* SkDebugf works in both visual studio and git shell, but
 in git shell output is not piped to grep.
 printf does not generate output in visual studio, but
 does in git shell and can be piped.
 */
#ifdef SK_BUILD_FOR_WIN
#define PRINTF(...)                 \
do {                                \
    if (IsDebuggerPresent()) {      \
        SkDebugf(__VA_ARGS__);      \
    } else {                        \
        printf(__VA_ARGS__);        \
    }                               \
} while (false)
#else
#define PRINTF(...)                 \
        printf(__VA_ARGS__)
#endif


// Check that mutiple like-named methods are under one Subtopic

// Check that SeeAlso reference each other

// Would be nice to check if other classes have 'create' methods that are included
//          SkSurface::makeImageSnapShot should be referenced under SkImage 'creators'

class SelfChecker {
public:
    SelfChecker(const BmhParser& bmh)
        : fBmhParser(bmh)
        {}

    bool check() {
        for (const auto& topic : fBmhParser.fTopicMap) {
            Definition* topicDef = topic.second;
            if (topicDef->fParent) {
                continue;
            }
            if (!topicDef->isRoot()) {
                return fBmhParser.reportError<bool>("expected root topic");
            }
            fRoot = topicDef->asRoot();
            if (!this->checkSeeAlso()) {
                return false;
            }
            // report functions that are not covered by related hierarchy
			if (!this->checkRelatedFunctions()) {
				return false;
			}
        }
        return true;
    }

protected:

    void checkMethod(string topic, const Definition* csChild, vector<string>* reported) {
        if (MarkType::kSubtopic == csChild->fMarkType) {
            for (auto child : csChild->fChildren) {
                checkMethod(topic, child, reported);
            }
            return;
        } else if (MarkType::kMethod != csChild->fMarkType) {
            // only check methods for now
            return;
        }
        bool containsMarkTypeIn =
                   Definition::MethodType::kConstructor == csChild->fMethodType
                || Definition::MethodType::kDestructor == csChild->fMethodType
                || Definition::MethodType::kOperator == csChild->fMethodType
                || csChild->fClone;
        for (auto child : csChild->fChildren) {
            if (MarkType::kIn == child->fMarkType) {
                containsMarkTypeIn = true;
                string subtopic(child->fContentStart,
                    child->fContentEnd - child->fContentStart);
                string fullname = topic + '_' + subtopic;
                auto topEnd = fBmhParser.fTopicMap.end();
                auto topFind = fBmhParser.fTopicMap.find(fullname);
                auto reportEnd = reported->end();
                auto reportFind = std::find(reported->begin(), reported->end(), subtopic);
                if (topEnd == topFind) {
                    if (reportEnd == reportFind) {
                        reported->push_back(subtopic);
                    }
                }
            }
        }
        if (!containsMarkTypeIn) {
            PRINTF("No #In: %s\n", csChild->fName.c_str());
        }
    }

	bool checkRelatedFunctions() {
		const Definition* cs = this->classOrStruct();
        if (!cs) {
            return true;
        }
        const Definition* topic = cs->fParent;
        SkASSERT(topic);
        SkASSERT(MarkType::kTopic == topic->fMarkType);
        string topicName = topic->fName;
        vector<string> methodNames;
        vector<string> reported;
		string prefix = cs->fName + "::";
		for (auto& csChild : cs->fChildren) {
            checkMethod(topicName, csChild, &reported);
		}
        for (auto missing : reported) {
            string fullname = topicName + '_' + missing;
            PRINTF("No #Subtopic: %s\n", fullname.c_str());
        }
		return true;
	}

    bool checkSeeAlso() {
        return true;
    }

	const Definition* classOrStruct() {
		for (auto& rootChild : fRoot->fChildren) {
			if (rootChild->isStructOrClass()) {
				return rootChild;
			}
		}
		return nullptr;
	}

	enum class Optional {
		kNo,
		kYes,
	};

private:
    const BmhParser& fBmhParser;
    RootDefinition* fRoot;
};

bool SelfCheck(const BmhParser& bmh) {
    SelfChecker checker(bmh);
    return checker.check();
}
