// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/ir/debug.h"

#include <unordered_map>
#include <unordered_set>

#include "src/tint/ir/block.h"
#include "src/tint/ir/continue.h"
#include "src/tint/ir/if.h"
#include "src/tint/ir/loop.h"
#include "src/tint/ir/return.h"
#include "src/tint/ir/switch.h"
#include "src/tint/switch.h"
#include "src/tint/utils/string_stream.h"

namespace tint::ir {

// static
std::string Debug::AsDotGraph(const Module* mod) {
    size_t block_count = 0;

    std::unordered_set<const Block*> visited;
    std::unordered_set<const Block*> merge_blocks;
    std::unordered_map<const Block*, std::string> block_to_name;
    utils::StringStream out;

    auto name_for = [&](const Block* blk) -> std::string {
        if (block_to_name.count(blk) > 0) {
            return block_to_name[blk];
        }

        std::string name = "blk_" + std::to_string(block_count);
        block_count += 1;

        block_to_name[blk] = name;
        return name;
    };

    std::function<void(const Block*)> Graph = [&](const Block* blk) {
        if (visited.count(blk) > 0) {
            return;
        }
        visited.insert(blk);

        tint::Switch(blk,  //
                     [&](const ir::Block* b) {
                         if (block_to_name.count(b) == 0) {
                             out << name_for(b) << R"( [label="block"])" << std::endl;
                         }
                         out << name_for(b) << " -> " << name_for(b->Branch()->To());

                         // Dashed lines to merge blocks
                         if (merge_blocks.count(b->Branch()->To()) != 0) {
                             out << " [style=dashed]";
                         }

                         out << std::endl;

                         if (b->Branch()->Is<ir::Return>()) {
                             return;
                         } else if (auto* cont = b->Branch()->As<ir::Continue>()) {
                             Graph(cont->Loop()->Continuing());
                         } else {
                             Graph(b->Branch()->To());
                         }
                     });
    };

    out << "digraph G {" << std::endl;
    for (const auto* func : mod->functions) {
        // Cluster each function to label and draw a box around it.
        out << "subgraph cluster_" << mod->NameOf(func).Name() << " {" << std::endl;
        out << R"(label=")" << mod->NameOf(func).Name() << R"(")" << std::endl;
        out << name_for(func->StartTarget()) << R"( [label="start"])" << std::endl;
        Graph(func->StartTarget());
        out << "}" << std::endl;
    }
    out << "}";
    return out.str();
}

}  // namespace tint::ir
