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

#include "tools/viewer/SkSLDebuggerSlide.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkStream.h"
#include "tools/viewer/Viewer.h"

#include <algorithm>
#include <cstdio>
#include "imgui.h"

using namespace sk_app;
using LineNumberMap = SkSL::SkVMDebugTracePlayer::LineNumberMap;

///////////////////////////////////////////////////////////////////////////////

SkSLDebuggerSlide::SkSLDebuggerSlide() {
    fName = "Debugger";
    fTrace = sk_make_sp<SkSL::SkVMDebugTrace>();
}

void SkSLDebuggerSlide::load(SkScalar winWidth, SkScalar winHeight) {}

void SkSLDebuggerSlide::unload() {
    fTrace = sk_make_sp<SkSL::SkVMDebugTrace>();
    fPlayer.reset(nullptr);
    fPlayer.setBreakpoints(std::unordered_set<int>{});
}

void SkSLDebuggerSlide::showLoadTraceGUI() {
    ImGui::InputText("Trace Path", fTraceFile, SK_ARRAY_COUNT(fTraceFile));
    bool load = ImGui::Button("Load Debug Trace");

    if (load) {
        SkFILEStream file(fTraceFile);
        if (!file.isValid()) {
            ImGui::OpenPopup("Can't Open Trace");
        } else if (!fTrace->readTrace(&file)) {
            ImGui::OpenPopup("Invalid Trace");
        } else {
            // Trace loaded successfully. On the next refresh, the user will see the debug UI.
            fPlayer.reset(fTrace);
            fPlayer.step();
            fRefresh = true;
            return;
        }
    }

    if (ImGui::BeginPopupModal("Can't Open Trace", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
        ImGui::Text("The trace file doesn't exist.");
        ImGui::Separator();
        if (ImGui::Button("OK", ImVec2(120, 0))) {
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }

    if (ImGui::BeginPopupModal("Invalid Trace", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
        ImGui::Text("The trace data could not be parsed.");
        ImGui::Separator();
        if (ImGui::Button("OK", ImVec2(120, 0))) {
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }
}

void SkSLDebuggerSlide::showDebuggerGUI() {
    if (ImGui::Button("Reset")) {
        fPlayer.reset(fTrace);
        fRefresh = true;
    }
    ImGui::SameLine(/*offset_from_start_x=*/0, /*spacing=*/100);
    if (ImGui::Button("Step")) {
        fPlayer.step();
        fRefresh = true;
    }
    ImGui::SameLine();
    if (ImGui::Button("Step Over")) {
        fPlayer.stepOver();
        fRefresh = true;
    }
    ImGui::SameLine();
    if (ImGui::Button("Step Out")) {
        fPlayer.stepOut();
        fRefresh = true;
    }
    ImGui::SameLine(/*offset_from_start_x=*/0, /*spacing=*/100);
    if (ImGui::Button(fPlayer.getBreakpoints().empty() ? "Run" : "Run to Breakpoint")) {
        fPlayer.run();
        fRefresh = true;
    }

    this->showStackTraceTable();
    this->showVariableTable();
    this->showCodeTable();
}

void SkSLDebuggerSlide::showCodeTable() {
    constexpr ImGuiTableFlags kTableFlags =
            ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
            ImGuiTableFlags_BordersV;
    constexpr ImGuiTableColumnFlags kColumnFlags =
            ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder |
            ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoSort |
            ImGuiTableColumnFlags_NoHeaderLabel;

    ImVec2 contentRect = ImGui::GetContentRegionAvail();
    ImVec2 codeViewSize = ImVec2(0.0f, contentRect.y);
    if (ImGui::BeginTable("Code View", /*column=*/2, kTableFlags, codeViewSize)) {
        ImGui::TableSetupColumn("", kColumnFlags | ImGuiTableColumnFlags_WidthFixed);
        ImGui::TableSetupColumn("Code", kColumnFlags | ImGuiTableColumnFlags_WidthStretch);

        ImGuiListClipper clipper;
        clipper.Begin(fTrace->fSource.size());
        while (clipper.Step()) {
            for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
                size_t humanReadableLine = row + 1;

                ImGui::TableNextRow();
                if (fPlayer.getCurrentLine() == (int)humanReadableLine) {
                    ImGui::TableSetBgColor(
                            ImGuiTableBgTarget_RowBg1,
                            ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_TextSelectedBg)));
                }

                // Show line numbers and breakpoints.
                ImGui::TableSetColumnIndex(0);
                const LineNumberMap& lineNumberMap = fPlayer.getLineNumbersReached();
                LineNumberMap::const_iterator iter = lineNumberMap.find(humanReadableLine);
                bool reachable = iter != lineNumberMap.end() && iter->second > 0;
                bool breakpointOn = fPlayer.getBreakpoints().count(humanReadableLine);
                if (breakpointOn) {
                    ImGui::PushStyleColor(ImGuiCol_Text,          ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
                    ImGui::PushStyleColor(ImGuiCol_Button,        ImVec4(1.0f, 0.0f, 0.0f, 0.70f));
                    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.0f, 0.0f, 0.85f));
                    ImGui::PushStyleColor(ImGuiCol_ButtonActive,  ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
                } else if (reachable) {
                    ImGui::PushStyleColor(ImGuiCol_Text,          ImVec4(1.0f, 1.0f, 1.0f, 0.75f));
                    ImGui::PushStyleColor(ImGuiCol_Button,        ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
                    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f));
                    ImGui::PushStyleColor(ImGuiCol_ButtonActive,  ImVec4(1.0f, 1.0f, 1.0f, 0.4f));
                } else {
                    ImGui::PushStyleColor(ImGuiCol_Text,          ImVec4(1.0f, 1.0f, 1.0f, 0.25f));
                    ImGui::PushStyleColor(ImGuiCol_Button,        ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
                    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
                    ImGui::PushStyleColor(ImGuiCol_ButtonActive,  ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
                }
                if (ImGui::SmallButton(SkStringPrintf("%03zu ", humanReadableLine).c_str())) {
                    if (breakpointOn) {
                        fPlayer.removeBreakpoint(humanReadableLine);
                    } else if (reachable) {
                        fPlayer.addBreakpoint(humanReadableLine);
                    }
                }
                ImGui::PopStyleColor(4);

                // Show lines of code.
                ImGui::TableSetColumnIndex(1);
                ImGui::Text("%s", fTrace->fSource[row].c_str());
            }
        }

        if (fRefresh) {
            int linesVisible = contentRect.y / ImGui::GetTextLineHeightWithSpacing();
            int centerLine = (fPlayer.getCurrentLine() - 1) - (linesVisible / 2);
            centerLine = std::max(0, centerLine);
            ImGui::SetScrollY(clipper.ItemsHeight * centerLine);
            fRefresh = false;
        }

        ImGui::EndTable();
    }
}

void SkSLDebuggerSlide::showStackTraceTable() {
    constexpr ImGuiTableFlags kTableFlags =
            ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
            ImGuiTableFlags_BordersV | ImGuiTableFlags_NoHostExtendX;
    constexpr ImGuiTableColumnFlags kColumnFlags =
            ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
            ImGuiTableColumnFlags_NoSort;

    std::vector<int> callStack = fPlayer.getCallStack();

    ImVec2 contentRect = ImGui::GetContentRegionAvail();
    ImVec2 stackViewSize = ImVec2(contentRect.x / 3.0f,
                                  ImGui::GetTextLineHeightWithSpacing() * kNumTopRows);
    if (ImGui::BeginTable("Call Stack", /*column=*/1, kTableFlags, stackViewSize)) {
        ImGui::TableSetupColumn("Stack", kColumnFlags);
        ImGui::TableHeadersRow();

        ImGuiListClipper clipper;
        clipper.Begin(callStack.size());
        while (clipper.Step()) {
            for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
                int funcIdx = callStack.rbegin()[row];
                SkASSERT(funcIdx >= 0 && (size_t)funcIdx < fTrace->fFuncInfo.size());
                const SkSL::SkVMFunctionInfo& funcInfo = fTrace->fFuncInfo[funcIdx];

                ImGui::TableNextRow();
                ImGui::TableSetColumnIndex(0);
                ImGui::Text("%s", funcInfo.name.c_str());
            }
        }
        ImGui::EndTable();
    }

    ImGui::SameLine();
}

void SkSLDebuggerSlide::showVariableTable() {
    constexpr ImGuiTableFlags kTableFlags =
            ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter |
            ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable;
    constexpr ImGuiTableColumnFlags kColumnFlags =
            ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoHide |
            ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthStretch;

    int frame = fPlayer.getStackDepth() - 1;
    std::vector<SkSL::SkVMDebugTracePlayer::VariableData> vars;
    if (frame >= 0) {
        vars = fPlayer.getLocalVariables(frame);
    } else {
        vars = fPlayer.getGlobalVariables();
    }
    ImVec2 varViewSize = ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * kNumTopRows);
    if (ImGui::BeginTable("Variables", /*column=*/2, kTableFlags, varViewSize)) {
        ImGui::TableSetupColumn("Variable", kColumnFlags);
        ImGui::TableSetupColumn("Value", kColumnFlags);
        ImGui::TableHeadersRow();
        if (!vars.empty()) {
            ImGuiListClipper clipper;
            clipper.Begin(vars.size());
            while (clipper.Step()) {
                for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
                    const SkSL::SkVMDebugTracePlayer::VariableData& var = vars.at(row);
                    SkASSERT(var.fSlotIndex >= 0);
                    SkASSERT((size_t)var.fSlotIndex < fTrace->fSlotInfo.size());
                    const SkSL::SkVMSlotInfo& slotInfo = fTrace->fSlotInfo[var.fSlotIndex];

                    ImGui::TableNextRow();
                    if (var.fDirty) {
                        // Highlight recently-changed variables.
                        ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg1,
                                               ImGui::GetColorU32(ImVec4{0.0f, 1.0f, 0.0f, 0.20f}));
                    }
                    ImGui::TableSetColumnIndex(0);
                    ImGui::Text("%s%s", slotInfo.name.c_str(),
                                        fTrace->getSlotComponentSuffix(var.fSlotIndex).c_str());
                    ImGui::TableSetColumnIndex(1);
                    ImGui::Text("%s",
                                fTrace->slotValueToString(var.fSlotIndex, var.fValue).c_str());
                }
            }
        }
        ImGui::EndTable();
    }
}

void SkSLDebuggerSlide::showRootGUI() {
    if (fTrace->fSource.empty()) {
        this->showLoadTraceGUI();
        return;
    }

    this->showDebuggerGUI();
}

void SkSLDebuggerSlide::draw(SkCanvas* canvas) {
    canvas->clear(SK_ColorWHITE);
    ImGui::Begin("Debugger", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar);
    this->showRootGUI();
    ImGui::End();
}

bool SkSLDebuggerSlide::animate(double nanos) {
    return true;
}
