// 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 <map>

#include "fidl/raw_ast.h"
#include "fidl/tree_visitor.h"

namespace fidl {
namespace raw {

void DeclarationOrderTreeVisitor::OnFile(std::unique_ptr<File> const& element) {
    OnSourceElementStart(*element);

    OnCompoundIdentifier(element->library_name);
    for (auto i = element->using_list.begin();
         i != element->using_list.end();
         ++i) {
        OnUsing(*i);
    }

    auto const_decls_it = element->const_declaration_list.begin();
    auto enum_decls_it = element->enum_declaration_list.begin();
    auto interface_decls_it = element->interface_declaration_list.begin();
    auto struct_decls_it = element->struct_declaration_list.begin();
    auto table_decls_it = element->table_declaration_list.begin();
    auto union_decls_it = element->union_declaration_list.begin();
    auto xunion_decls_it = element->xunion_declaration_list.begin();

    enum Next {
        const_t,
        enum_t,
        interface_t,
        struct_t,
        table_t,
        union_t,
        xunion_t,
    };

    std::map<const char*, Next> m;
    do {
        // We want to visit these in declaration order, rather than grouped
        // by type of declaration.  std::map is sorted by key.  For each of
        // these lists of declarations, we make a map where the key is "the
        // next start location of the earliest element in the list" to a
        // variable representing the type.  We then identify which type was
        // put earliest in the map.  That will be the earliest declaration
        // in the file.  We then visit the declaration accordingly.
        m.clear();
        if (const_decls_it != element->const_declaration_list.end()) {
            m[(*const_decls_it)->start_.previous_end().data().data()] = const_t;
        }
        if (enum_decls_it != element->enum_declaration_list.end()) {
            m[(*enum_decls_it)->start_.previous_end().data().data()] = enum_t;
        }
        if (interface_decls_it != element->interface_declaration_list.end()) {
            if (*interface_decls_it == nullptr) {
                // Used to indicate empty, so let's wind it forward.
                interface_decls_it = element->interface_declaration_list.end();
            } else {
                m[(*interface_decls_it)->start_.previous_end().data().data()] = interface_t;
            }
        }
        if (struct_decls_it != element->struct_declaration_list.end()) {
            m[(*struct_decls_it)->start_.previous_end().data().data()] = struct_t;
        }
        if (table_decls_it != element->table_declaration_list.end()) {
            m[(*table_decls_it)->start_.previous_end().data().data()] = table_t;
        }
        if (union_decls_it != element->union_declaration_list.end()) {
            m[(*union_decls_it)->start_.previous_end().data().data()] = union_t;
        }
        if (xunion_decls_it != element->xunion_declaration_list.end()) {
            m[(*xunion_decls_it)->start_.previous_end().data().data()] = xunion_t;
        }
        if (m.size() == 0)
            break;

        // And the earliest top level declaration is...
        switch (m.begin()->second) {
        case const_t:
            OnConstDeclaration(*const_decls_it);
            ++const_decls_it;
            break;
        case enum_t:
            OnEnumDeclaration(*enum_decls_it);
            ++enum_decls_it;
            break;
        case interface_t:
            OnInterfaceDeclaration(*interface_decls_it);
            ++interface_decls_it;
            break;
        case struct_t:
            OnStructDeclaration(*struct_decls_it);
            ++struct_decls_it;
            break;
        case table_t:
            OnTableDeclaration(*table_decls_it);
            ++table_decls_it;
            break;
        case union_t:
            OnUnionDeclaration(*union_decls_it);
            ++union_decls_it;
            break;
        case xunion_t:
            OnXUnionDeclaration(*xunion_decls_it);
            ++xunion_decls_it;
            break;
        }
    } while (1);
    OnSourceElementEnd(*element);
}

} // namespace raw
} // namespace fidl
