/*
 * 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().build());
            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;
}
