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

#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkPath.h"
#include "samplecode/Sample.h"

#include "modules/sksg/include/SkSGDraw.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "modules/sksg/include/SkSGRect.h"
#include "modules/sksg/include/SkSGScene.h"

struct PerNodeInfo {
    // key
    sksg::Draw* fDraw;

    // value(s)
    sksg::GeometryNode* fGeo;
    sksg::PaintNode*    fPaint;
};

class SampleSG : public Sample {
    SkTDArray<PerNodeInfo> fSideCar;
    sk_sp<sksg::Group> fGroup;
    std::unique_ptr<sksg::Scene> fScene;

    PerNodeInfo* findInfo(sksg::Draw* key) {
        for (int i = 0; i < fSideCar.count(); ++i) {
            if (fSideCar[i].fDraw == key) {
                return &fSideCar[i];
            }
        }
        return nullptr;
    }

    void appendNode(sk_sp<sksg::Draw> d, sk_sp<sksg::GeometryNode> g, sk_sp<sksg::PaintNode> p) {
        fGroup->addChild(d);
        auto sc = fSideCar.append();
        sc->fDraw  = d.get();
        sc->fGeo   = g.get();
        sc->fPaint = p.get();
    }

public:
    SampleSG() {
        fGroup = sksg::Group::Make();

        fScene = sksg::Scene::Make(fGroup);

        auto r = sksg::Rect::Make({20, 20, 400, 300});
        auto p = sksg::Color::Make(SK_ColorRED);
        auto d = sksg::Draw::Make(r, p);
        this->appendNode(d, r, p);

        r = sksg::Rect::Make({60, 70, 300, 400});
        p = sksg::Color::Make(SK_ColorBLUE);
        d = sksg::Draw::Make(r, p);
        this->appendNode(d, r, p);
    }

protected:
    SkString name() override { return SkString("SceneGraph"); }

    void onDrawContent(SkCanvas* canvas) override {
        fScene->render(canvas);
    }

    Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
        if (auto node = fScene->nodeAt({x, y})) {
            Click* click = new Click();
            click->fMeta.setPtr("node", (void*)node);
            return click;
        }
        return nullptr;
    }

    bool onClick(Click* click) override {
        sksg::Draw* node = nullptr;
        if (click->fMeta.findPtr("node", (void**)&node)) {
            if (auto info = this->findInfo(node)) {
                auto geo = info->fGeo;
                sksg::Rect* r = (sksg::Rect*)geo;
                SkScalar dx = click->fCurr.fX - click->fPrev.fX;
                SkScalar dy = click->fCurr.fY - click->fPrev.fY;
                r->setL(r->getL() + dx);
                r->setR(r->getR() + dx);
                r->setT(r->getT() + dy);
                r->setB(r->getB() + dy);
            }
            return true;
        }
        return false;
    }

private:

    using INHERITED = Sample;
};

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

DEF_SAMPLE( return new SampleSG(); )
