/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "modules/jetski/src/SurfaceThread.h"

#include "tools/window/DisplayParams.h"
#include "tools/window/WindowContext.h"
#include "tools/window/android/WindowContextFactory_android.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkPicture.h"
#include "include/core/SkTypes.h"

SurfaceThread::SurfaceThread() {
    pipe(fPipe);
    fRunning = true;
    pthread_create(&fThread, nullptr, pthread_main, this);
}

void SurfaceThread::postMessage(const Message& message) const {
    write(fPipe[1], &message, sizeof(message));
}

void SurfaceThread::readMessage(Message* message) const {
    read(fPipe[0], message, sizeof(Message));
}

void SurfaceThread::release() {
    pthread_join(fThread, nullptr);
}

int SurfaceThread::message_callback(int /* fd */, int /* events */, void* data) {
    auto surfaceThread = (SurfaceThread*)data;
    Message message;
    surfaceThread->readMessage(&message);
    // get target surface from Message

    switch (message.fType) {
        case kInitialize: {
            auto winctx = skwindow::MakeGLForAndroid(message.fNativeWindow,
                                                     skwindow::DisplayParamsBuilder().detach());
            if (!winctx) {
                break;
            }
            *message.fWindowSurface = new WindowSurface(message.fNativeWindow, std::move(winctx));
            break;
        }
        case kDestroy: {
            SkDebugf("surface destroyed, shutting down thread");
            surfaceThread->fRunning = false;
            if(auto* windowSurface = reinterpret_cast<Surface*>(*message.fWindowSurface)){
                windowSurface->release(nullptr);
                delete windowSurface;
            }
            return 0;
        }
        case kRenderPicture: {
            sk_sp<SkPicture> picture(message.fPicture);
            if(auto* windowSurface = reinterpret_cast<Surface*>(*message.fWindowSurface)){
                windowSurface->getCanvas()->drawPicture(picture);
                windowSurface->flushAndSubmit();
            }
            break;
        }
        default: {
            // do nothing
        }
    }

    return 1;  // continue receiving callbacks
}

void* SurfaceThread::pthread_main(void* arg) {
    auto surfaceThread = (SurfaceThread*)arg;
    // Looper setup
    ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
    ALooper_addFd(looper, surfaceThread->fPipe[0], 1, ALOOPER_EVENT_INPUT,
               surfaceThread->message_callback, surfaceThread);

    while (surfaceThread->fRunning) {
        int ident = ALOOPER_POLL_CALLBACK;
        while (ident == ALOOPER_POLL_CALLBACK) {
            ident = ALooper_pollOnce(0, nullptr, nullptr, nullptr);
        }

        if (ident >= 0) {
            SkDebugf("Unhandled ALooper_pollOnce ident=%d !", ident);
        }
    }
    return nullptr;
}
