#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>

#include "GrContext.h"
#include "SkGpuCanvas.h"
#include "SkPaint.h"
#include "SkString.h"
#include "SkTime.h"

#include "GrGLConfig.h"

static GrContext* make_context() {
    SkDebugf("---- before create\n");
    GrContext* ctx = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, 0);
//    GrContext* ctx = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, 0);
    SkDebugf("---- after create %p\n", ctx);
    return ctx;
}

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

void gr_run_unittests() {}

#include "FlingState.h"
#include "GrTouchGesture.h"
#include "SkView.h"

typedef SkView* (*SkViewFactory)();

// these values must match those in Ganesh.java
enum TouchState {
    kUnknown_TouchState,
    kDown_TouchState,
    kMoved_TouchState,
    kUp_TouchState
};

struct State {
    State();
    ~State();

    int countSlides() const { return fFactory.count(); }
    const char* getSlideTitle(int index) const;
    void chooseSlide(int index) {
        SkDebugf("----- index %d\n", index);
        if (index < fFactory.count()) {
            this->setView(fFactory[index]());
        }
    }

    void setViewport(int w, int h);
    int getWidth() const { return fViewport.fX; }
    int getHeight() const { return fViewport.fY; }
    
    void handleTouch(void*, TouchState, float x, float y);
    void applyMatrix(SkCanvas*);

    SkView* getView() const { return fView; }

private:
    SkView*     fView;
    SkIPoint    fViewport;
    
    GrTouchGesture fGesture;

    SkTDArray<SkViewFactory> fFactory;

    void setView(SkView* view) {
        SkSafeUnref(fView);
        fView = view;

        view->setVisibleP(true);
        view->setClipToBounds(false);
        view->setSize(SkIntToScalar(fViewport.fX),
                      SkIntToScalar(fViewport.fY));
    }
};

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

#include "SampleCode.h"

SkViewRegister* SkViewRegister::gHead;
SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
    static bool gOnce;
    if (!gOnce) {
        gHead = NULL;
        gOnce = true;
    }
    
    fChain = gHead;
    gHead = this;
}

static const char gCharEvtName[] = "SampleCode_Char_Event";
static const char gKeyEvtName[] = "SampleCode_Key_Event";
static const char gTitleEvtName[] = "SampleCode_Title_Event";
static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
static const char gFastTextEvtName[] = "SampleCode_FastText_Event";

bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
    if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
        if (outUni) {
            *outUni = evt.getFast32();
        }
        return true;
    }
    return false;
}

bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
    if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
        if (outKey) {
            *outKey = (SkKey)evt.getFast32();
        }
        return true;
    }
    return false;
}

bool SampleCode::TitleQ(const SkEvent& evt) {
    return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
}

void SampleCode::TitleR(SkEvent* evt, const char title[]) {
    GrAssert(evt && TitleQ(*evt));
    evt->setString(gTitleEvtName, title);
}

bool SampleCode::PrefSizeQ(const SkEvent& evt) {
    return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
}

void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
    GrAssert(evt && PrefSizeQ(*evt));
    SkScalar size[2];
    size[0] = width;
    size[1] = height;
    evt->setScalars(gPrefSizeEvtName, 2, size);
}

bool SampleCode::FastTextQ(const SkEvent& evt) {
    return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
}

static SkMSec gAnimTime;
static SkMSec gAnimTimePrev;

SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
SkScalar SampleCode::GetAnimSecondsDelta() {
    return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
}

SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
    // since gAnimTime can be up to 32 bits, we can't convert it to a float
    // or we'll lose the low bits. Hence we use doubles for the intermediate
    // calculations
    double seconds = (double)gAnimTime / 1000.0;
    double value = SkScalarToDouble(speed) * seconds;
    if (period) {
        value = ::fmod(value, SkScalarToDouble(period));
    }
    return SkDoubleToScalar(value);
}

static void drawIntoCanvas(State* state, SkCanvas* canvas) {
    gAnimTime = SkTime::GetMSecs();
    SkView* view = state->getView();
    view->draw(canvas);
}

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

static void resetGpuState();

State::State() {
    fViewport.set(0, 0);

    const SkViewRegister* reg = SkViewRegister::Head();
    while (reg) {
        *fFactory.append() = reg->factory();
        reg = reg->next();
    }

    SkDebugf("----- %d slides\n", fFactory.count());
    fView = NULL;
    this->chooseSlide(0);
}

State::~State() {
    SkSafeUnref(fView);
}

void State::setViewport(int w, int h) {
    fViewport.set(w, h);
    if (fView) {
        fView->setSize(SkIntToScalar(w), SkIntToScalar(h));
    }
    resetGpuState();
}

const char* State::getSlideTitle(int index) const {
    SkEvent evt(gTitleEvtName);
    evt.setFast32(index);
    {
        SkView* view = fFactory[index]();
        view->doQuery(&evt);
        view->unref();
    }
    return evt.findString(gTitleEvtName);
}

void State::handleTouch(void* owner, TouchState state, float x, float y) {
    switch (state) {
        case kDown_TouchState:
            fGesture.touchBegin(owner, x, y);
            break;
        case kMoved_TouchState:
            fGesture.touchMoved(owner, x, y);
            break;
        case kUp_TouchState:
            fGesture.touchEnd(owner);
            break;
    }
}

void State::applyMatrix(SkCanvas* canvas) {
    const SkMatrix& localM = fGesture.localM();
    if (localM.getType() & SkMatrix::kScale_Mask) {
        canvas->setExternalMatrix(&localM);
    }
    canvas->concat(localM);
    canvas->concat(fGesture.globalM());
}

static State* get_state() {
    static State* gState;
    if (NULL == gState) {
        gState = new State;
    }
    return gState;
}

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

static GrContext* gContext;
static int gWidth;
static int gHeight;
static float gX, gY;

static void resetGpuState() {
    if (NULL == gContext) {
        SkDebugf("creating context for first time\n");
        gContext = make_context();
    } else {
        SkDebugf("------ gContext refcnt=%d\n", gContext->refcnt());
        gContext->abandonAllTextures();
        gContext->unref();
        gContext = make_context();
    }
}

static void doDraw() {
    if (NULL == gContext) {
        gContext = make_context();
    }

    State* state = get_state();
    SkBitmap viewport;
    viewport.setConfig(SkBitmap::kARGB_8888_Config,
                       state->getWidth(), state->getHeight());

    SkGpuCanvas canvas(gContext);

    canvas.setBitmapDevice(viewport);
    state->applyMatrix(&canvas);

    drawIntoCanvas(state, &canvas);

    GrGLCheckErr();
    GrGLClearErr();
//    gContext->checkError();
//    gContext->clearError();

    if (true) {
        static const int FRAME_COUNT = 32;
        static SkMSec gDuration;

        static SkMSec gNow;
        static int gFrameCounter;
        if (++gFrameCounter == FRAME_COUNT) {
            gFrameCounter = 0;
            SkMSec now = SkTime::GetMSecs();

            gDuration = now - gNow;
            gNow = now;
        }

        int fps = (FRAME_COUNT * 1000) / gDuration;
        SkString str;
        str.printf("FPS=%3d MS=%3d", fps, gDuration / FRAME_COUNT);
        
        SkGpuCanvas c(gContext);
        c.setBitmapDevice(viewport);

        SkPaint p;
        p.setAntiAlias(true);
        SkRect r = { 0, 0, 110, 16 };
        p.setColor(SK_ColorWHITE);
        c.drawRect(r, p);
        p.setColor(SK_ColorBLACK);
        c.drawText(str.c_str(), str.size(), 4, 12, p);
    }
}

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

extern "C" {
    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeSurfaceCreated(
                                                           JNIEnv*, jobject);
    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeViewport(JNIEnv*, jobject,
                                                                             jint w, jint h);
    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeDrawFrame(JNIEnv*, jobject);
    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeTouch(JNIEnv*, jobject,
                                        jint id, jint type, jfloat x, jfloat y);

    JNIEXPORT int JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeCountSlides(JNIEnv*, jobject);
    JNIEXPORT jobject JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeGetSlideTitle(JNIEnv*, jobject, jint index);
    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeChooseSlide(JNIEnv*, jobject, jint index);
}

JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeSurfaceCreated(
                                                            JNIEnv*, jobject) {
    SkDebugf("------ nativeSurfaceCreated\n");
    resetGpuState();
    SkDebugf("------ end nativeSurfaceCreated\n");
}

JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeViewport(JNIEnv*, jobject,
                                                       jint w, jint h) {
    State* state = get_state();
    SkDebugf("---- state.setviewport %p %d %d\n", state, w, h);
    state->setViewport(w, h);
    SkDebugf("---- end setviewport\n");
}

JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeDrawFrame(JNIEnv*, jobject) {
    doDraw();
}

union IntPtr {
    jint    fInt;
    void*   fPtr;
};
static void* int2ptr(jint n) {
    IntPtr data;
    data.fInt = n;
    return data.fPtr;
}

JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeTouch(JNIEnv*, jobject,
                                      jint id, jint type, jfloat x, jfloat y) {
    get_state()->handleTouch(int2ptr(id), (TouchState)type, x, y);
}

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

JNIEXPORT int JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeCountSlides(JNIEnv*, jobject) {
    return get_state()->countSlides();
}

JNIEXPORT jobject JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeGetSlideTitle(JNIEnv* env, jobject, jint index) {
    return env->NewStringUTF(get_state()->getSlideTitle(index));
}

JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeChooseSlide(JNIEnv*, jobject, jint index) {
    get_state()->chooseSlide(index);
}





