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


#include "gm.h"
#include "SkPathEffect.h"
#include "SkPictureRecorder.h"
#include "SkShadowPaintFilterCanvas.h"
#include "SkShadowShader.h"
#include "SkSurface.h"

#ifdef SK_EXPERIMENTAL_SHADOWING


static sk_sp<SkPicture> make_test_picture(int width, int height) {
    SkPictureRecorder recorder;

    // LONG RANGE TODO: eventually add SkBBHFactory (bounding box factory)
    SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height));

    SkASSERT(canvas->getTotalMatrix().isIdentity());
    SkPaint paint;
    paint.setColor(SK_ColorGRAY);

    // LONG RANGE TODO: tag occluders
    // LONG RANGE TODO: track number of IDs we need (hopefully less than 256)
    //                  and determinate the mapping from z to id

    // universal receiver, "ground"
    canvas->drawRect(SkRect::MakeIWH(width, height), paint);

    // TODO: Maybe add the ID here along with the depth

    paint.setColor(0xFFEE8888);

    canvas->translateZ(80);
    canvas->drawRect(SkRect::MakeLTRB(200,150,350,300), paint);

    paint.setColor(0xFF88EE88);

    canvas->translateZ(80);
    canvas->drawRect(SkRect::MakeLTRB(150,200,300,350), paint);

    paint.setColor(0xFF8888EE);

    canvas->translateZ(80);
    canvas->drawRect(SkRect::MakeLTRB(100,100,250,250), paint);
    // TODO: Add an assert that Z order matches painter's order
    // TODO: think about if the Z-order always matching painting order is too strict

    return recorder.finishRecordingAsPicture();
}

namespace skiagm {

class ShadowMapsGM : public GM {
public:
    ShadowMapsGM() {
        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
    }

    void onOnceBeforeDraw() override {
        // Create a light set consisting of
        //   - bluish directional light pointing more right than down
        //   - reddish directional light pointing more down than right
        //   - soft white ambient light

        SkLights::Builder builder;
        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.2f, 0.3f, 0.4f),
                                                     SkVector3::Make(0.2f, 0.1f, 1.0f)));
        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.4f, 0.3f, 0.2f),
                                                     SkVector3::Make(0.1f, 0.2f, 1.0f)));
        builder.setAmbientLightColor(SkColor3f::Make(0.4f, 0.4f, 0.4f));
        fLights = builder.finish();

        fShadowParams.fShadowRadius = 4.0f;
        fShadowParams.fBiasingConstant = 0.3f;
        fShadowParams.fMinVariance = 1024;
        fShadowParams.fType = SkShadowParams::kVariance_ShadowType;
    }

protected:
    static constexpr int kWidth = 400;
    static constexpr int kHeight = 400;

    SkString onShortName() override {
        return SkString("shadowmaps");
    }

    SkISize onISize() override {
        return SkISize::Make(kWidth, kHeight);
    }

    void onDraw(SkCanvas* canvas) override {
        // This picture stores the picture of the scene.
        // It's used to generate the depth maps.
        sk_sp<SkPicture> pic(make_test_picture(kWidth, kHeight));
        canvas->setLights(fLights);
        canvas->drawShadowedPicture(pic, nullptr, nullptr, fShadowParams);
    }

private:
    sk_sp<SkLights> fLights;
    SkShadowParams fShadowParams;
    typedef GM INHERITED;
};

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

DEF_GM(return new ShadowMapsGM;)
}

#endif
