/*
 * 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 "SkRandom.h"
#include "SkString.h"
#if SK_SUPPORT_GPU
#include "GrOrderedSet.h"

static const int NUM_ELEMENTS = 1000;

// Time how long it takes to build a set
class GrOrderedSetBuildBench : public Benchmark {
public:
    GrOrderedSetBuildBench() {
        fName.append("ordered_set_build");
    }

    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return kNonRendering_Backend == backend;
    }

    virtual ~GrOrderedSetBuildBench() {}

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

    virtual void onPreDraw() SK_OVERRIDE {
        SkRandom rand;
        for (int j = 0; j < NUM_ELEMENTS; ++j) {
            fData[j] = rand.nextU() % NUM_ELEMENTS;
        }
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        for (int i = 0; i < loops; ++i) {
            GrOrderedSet<int> set;
            for (int j = 0; j < NUM_ELEMENTS; ++j) {
                set.insert(fData[j]);
            }
            set.reset();
        }
    }

private:
    SkString fName;
    int fData[NUM_ELEMENTS];
    typedef Benchmark INHERITED;
};

// Time how long it takes to find elements in a set
class GrOrderedSetFindBench : public Benchmark {
public:
    GrOrderedSetFindBench() {
        fName.append("ordered_set_find");
    }

    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return kNonRendering_Backend == backend;
    }

    virtual ~GrOrderedSetFindBench() {}

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

    virtual void onPreDraw() SK_OVERRIDE {
        SkRandom rand;
        for (int j = 0; j < NUM_ELEMENTS; ++j) {
            fData[j] = rand.nextU() % 1500;
            fSet.insert(rand.nextU() % NUM_ELEMENTS);
        }
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        for (int i = 0; i < loops; ++i) {
            for (int j = 0; j < NUM_ELEMENTS; ++j) {
                fSet.find(fData[j]);
            }
        }
    }

private:
    SkString fName;
    int fData[NUM_ELEMENTS];
    GrOrderedSet<int> fSet;
    typedef Benchmark INHERITED;
};

// Time how long it takes to iterate over and remove all elements from set
class GrOrderedSetRemoveBench : public Benchmark {
public:
    GrOrderedSetRemoveBench() {
        fName.append("ordered_set_remove");
    }

    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return kNonRendering_Backend == backend;
    }

    virtual ~GrOrderedSetRemoveBench() {}

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

    virtual void onPreDraw() SK_OVERRIDE {
        SkRandom rand;
        for (int j = 0; j < NUM_ELEMENTS; ++j) {
            fSet.insert(rand.nextU() % NUM_ELEMENTS);
        }
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        typedef GrOrderedSet<int>::Iter SetIter;
        for (int i = 0; i < loops; ++i) {
            GrOrderedSet<int> testSet;
            for (SetIter s = fSet.begin(); fSet.end() != s; ++s) {
                testSet.insert(*s);
            }
            for (int j = 0; j < NUM_ELEMENTS; ++j) {
                testSet.remove(testSet.find(j));
            }
        }
    }

private:
    SkString fName;
    GrOrderedSet<int> fSet;
    typedef Benchmark INHERITED;
};

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

DEF_BENCH(return SkNEW_ARGS(GrOrderedSetBuildBench, ());)
DEF_BENCH(return SkNEW_ARGS(GrOrderedSetFindBench, ());)
DEF_BENCH(return SkNEW_ARGS(GrOrderedSetRemoveBench, ());)
#endif
