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

#ifndef ImGuiLayer_DEFINED
#define ImGuiLayer_DEFINED

#include "include/core/SkPaint.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTPin.h"
#include "tools/sk_app/Window.h"

#include "imgui.h"

namespace ImGui {

// Helper object for drawing in a widget region, with draggable points
struct DragCanvas {
    DragCanvas(const void* id, SkPoint tl = { 0.0f, 0.0f }, SkPoint br = { 1.0f, 1.0f },
               float aspect = -1.0f)
            : fID(0), fDragging(false) {
        ImGui::PushID(id);
        fDrawList = ImGui::GetWindowDrawList();

        // Logical size
        SkScalar w = SkTAbs(br.fX - tl.fX),
                 h = SkTAbs(br.fY - tl.fY);

        // Determine aspect ratio automatically by default
        if (aspect < 0) {
            aspect = h / w;
        }

        float availWidth = std::max(ImGui::GetContentRegionAvailWidth(), 1.0f);
        fPos = ImGui::GetCursorScreenPos();
        fSize = ImVec2(availWidth, availWidth * aspect);

        SkPoint local[4] = {
            { tl.fX, tl.fY },
            { br.fX, tl.fY },
            { tl.fX, br.fY },
            { br.fX, br.fY },
        };
        SkPoint screen[4] = {
            { fPos.x          , fPos.y           },
            { fPos.x + fSize.x, fPos.y           },
            { fPos.x          , fPos.y + fSize.y },
            { fPos.x + fSize.x, fPos.y + fSize.y },
        };
        fLocalToScreen.setPolyToPoly(local, screen, 4);
        fScreenToLocal.setPolyToPoly(screen, local, 4);
    }

    ~DragCanvas() {
        ImGui::SetCursorScreenPos(ImVec2(fPos.x, fPos.y + fSize.y));
        ImGui::Spacing();
        ImGui::PopID();
    }

    void fillColor(ImU32 color) {
        fDrawList->AddRectFilled(fPos, ImVec2(fPos.x + fSize.x, fPos.y + fSize.y), color);
    }

    void dragPoint(SkPoint* p, bool tooltip = false, ImU32 color = 0xFFFFFFFF) {
        // Transform points from logical coordinates to screen coordinates
        SkPoint center = fLocalToScreen.mapXY(p->fX, p->fY);

        // Invisible 10x10 button
        ImGui::PushID(fID++);
        ImGui::SetCursorScreenPos(ImVec2(center.fX - 5, center.fY - 5));
        ImGui::InvisibleButton("", ImVec2(10, 10));

        if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
            // Update screen position to track mouse, clamped to our area
            ImGuiIO& io = ImGui::GetIO();
            center.set(SkTPin(io.MousePos.x, fPos.x, fPos.x + fSize.x),
                       SkTPin(io.MousePos.y, fPos.y, fPos.y + fSize.y));

            // Update local coordinates for the caller
            *p = fScreenToLocal.mapXY(center.fX, center.fY);
            fDragging = true;
        }

        if (tooltip && ImGui::IsItemHovered()) {
            ImGui::SetTooltip("x: %.3f\ny: %.3f", p->fX, p->fY);
        }

        ImGui::PopID();

        fScreenPoints.push_back(ImVec2(center.fX, center.fY));
        fDrawList->AddCircle(fScreenPoints.back(), 5.0f, color);
    }

    ImDrawList* fDrawList;

    // Location and dimensions (in screen coordinates)
    ImVec2 fPos;
    ImVec2 fSize;

    // Screen coordinates of points (for additional user drawing)
    SkSTArray<4, ImVec2, true> fScreenPoints;

    // To simplify dragPoint
    SkMatrix fLocalToScreen;
    SkMatrix fScreenToLocal;

    int fID;
    bool fDragging;
};

}  // namespace ImGui

class ImGuiLayer : public sk_app::Window::Layer {
public:
    ImGuiLayer();
    ~ImGuiLayer() override;

    void setScaleFactor(float scaleFactor);

    typedef std::function<void(SkCanvas*)> SkiaWidgetFunc;
    void skiaWidget(const ImVec2& size, SkiaWidgetFunc func);

    void onAttach(sk_app::Window* window) override;
    void onPrePaint() override;
    void onPaint(SkSurface*) override;
    bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override;
    bool onMouseWheel(float delta, skui::ModifierKey modifiers) override;
    bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override;
    bool onChar(SkUnichar c, skui::ModifierKey modifiers) override;

private:
    sk_app::Window* fWindow;
    SkPaint fFontPaint;
    SkTArray<SkiaWidgetFunc> fSkiaWidgetFuncs;
};

#endif
