/*
* 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 "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;
};

}

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

    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
