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

#include "Benchmark.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkNullCanvas.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkString.h"

class PictureNesting : public Benchmark {
public:
    PictureNesting(const char* name, int maxLevel, int maxPictureLevel)
        : fMaxLevel(maxLevel)
        , fMaxPictureLevel(maxPictureLevel) {
        fName.printf("picture_nesting_%s_%d", name, this->countPics());
        fPaint.setColor(SK_ColorRED);
        fPaint.setAntiAlias(true);
        fPaint.setStyle(SkPaint::kStroke_Style);
    }

protected:
    const char* onGetName() override {
        return fName.c_str();
    }

    void doDraw(SkCanvas* canvas) {
        SkIPoint canvasSize = onGetSize();
        canvas->save();
        canvas->scale(SkIntToScalar(canvasSize.x()), SkIntToScalar(canvasSize.y()));

        SkDEBUGCODE(int pics = ) this->sierpinsky(canvas, 0, fPaint);
        SkASSERT(pics == this->countPics());

        canvas->restore();
    }

    int sierpinsky(SkCanvas* canvas, int lvl, const SkPaint& paint) {
        if (++lvl > fMaxLevel) {
            return 0;
        }

        int pics = 0;
        bool recordPicture = lvl <= fMaxPictureLevel;
        SkPictureRecorder recorder;
        SkCanvas* c = canvas;

        if (recordPicture) {
            c = recorder.beginRecording(1, 1);
            pics++;
        }

        c->drawLine(0.5, 0, 0, 1, paint);
        c->drawLine(0.5, 0, 1, 1, paint);
        c->drawLine(0,   1, 1, 1, paint);

        c->save();
            c->scale(0.5, 0.5);

            c->translate(0, 1);
            pics += this->sierpinsky(c, lvl, paint);

            c->translate(1, 0);
            pics += this->sierpinsky(c, lvl, paint);

            c->translate(-0.5, -1);
            pics += this->sierpinsky(c, lvl, paint);
        c->restore();

        if (recordPicture) {
            canvas->drawPicture(recorder.finishRecordingAsPicture());
        }

        return pics;
    }

    int fMaxLevel;
    int fMaxPictureLevel;

private:
    int countPics() const {
        // Solve: pics from sierpinsky
        // f(m) = 1 + 3*f(m - 1)
        // f(0) = 0
        //   via "recursive function to closed form" tricks
        // f(m) = 1/2 (3^m - 1)
        int pics = 1;
        for (int i = 0; i < fMaxPictureLevel; i++) {
            pics *= 3;
        }
        pics--;
        pics /= 2;
        return pics;
    }

    SkString fName;
    SkPaint  fPaint;

    typedef Benchmark INHERITED;
};

class PictureNestingRecording : public PictureNesting {
public:
    PictureNestingRecording(int maxLevel, int maxPictureLevel)
        : INHERITED("recording", maxLevel, maxPictureLevel) {
    }

protected:
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }

    void onDraw(int loops, SkCanvas*) override {
        SkIPoint canvasSize = onGetSize();
        SkPictureRecorder recorder;

        for (int i = 0; i < loops; i++) {
            SkCanvas* c = recorder.beginRecording(SkIntToScalar(canvasSize.x()),
                                                  SkIntToScalar(canvasSize.y()));
            this->doDraw(c);
            (void)recorder.finishRecordingAsPicture();
        }
    }

private:
    typedef PictureNesting INHERITED;
};

class PictureNestingPlayback : public PictureNesting {
public:
    PictureNestingPlayback(int maxLevel, int maxPictureLevel)
        : INHERITED("playback", maxLevel, maxPictureLevel) {
    }
protected:
    void onDelayedSetup() override {
        this->INHERITED::onDelayedSetup();

        SkIPoint canvasSize = onGetSize();
        SkPictureRecorder recorder;
        SkCanvas* c = recorder.beginRecording(SkIntToScalar(canvasSize.x()),
                                              SkIntToScalar(canvasSize.y()));

        this->doDraw(c);
        fPicture = recorder.finishRecordingAsPicture();
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        for (int i = 0; i < loops; i++) {
            canvas->drawPicture(fPicture);
        }
    }

private:
    sk_sp<SkPicture> fPicture;

    typedef PictureNesting INHERITED;
};

DEF_BENCH( return new PictureNestingRecording(8, 0); )
DEF_BENCH( return new PictureNestingRecording(8, 1); )
DEF_BENCH( return new PictureNestingRecording(8, 2); )
DEF_BENCH( return new PictureNestingRecording(8, 3); )
DEF_BENCH( return new PictureNestingRecording(8, 4); )
DEF_BENCH( return new PictureNestingRecording(8, 5); )
DEF_BENCH( return new PictureNestingRecording(8, 6); )
DEF_BENCH( return new PictureNestingRecording(8, 7); )
DEF_BENCH( return new PictureNestingRecording(8, 8); )

DEF_BENCH( return new PictureNestingPlayback(8, 0); )
DEF_BENCH( return new PictureNestingPlayback(8, 1); )
DEF_BENCH( return new PictureNestingPlayback(8, 2); )
DEF_BENCH( return new PictureNestingPlayback(8, 3); )
DEF_BENCH( return new PictureNestingPlayback(8, 4); )
DEF_BENCH( return new PictureNestingPlayback(8, 5); )
DEF_BENCH( return new PictureNestingPlayback(8, 6); )
DEF_BENCH( return new PictureNestingPlayback(8, 7); )
DEF_BENCH( return new PictureNestingPlayback(8, 8); )
