// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <CoreServices/CoreServices.h>
#include <jni.h>
#include <pthread.h>
#include <stdlib.h>

#include <list>
#include <string>

namespace {

// A structure to pass around the FSEvents info and the list of paths.
struct JNIEventsDiffAwareness {
  // FSEvents run loop (thread)
  CFRunLoopRef runLoop;

  // FSEvents stream reference (reference to the listened stream)
  FSEventStreamRef stream;

  // If true, fsevents dropped events so we don't know what changed exactly.
  bool everything_changed;

  // List of paths that have been changed since last polling.
  std::list<std::string> paths;

  // Mutex to protect concurrent accesses to paths and everything_changed.
  pthread_mutex_t mutex;

  JNIEventsDiffAwareness() : everything_changed(false) {
    pthread_mutex_init(&mutex, nullptr);
  }

  ~JNIEventsDiffAwareness() { pthread_mutex_destroy(&mutex); }
};

// Callback called when an event is reported by the FSEvents API
void FsEventsDiffAwarenessCallback(ConstFSEventStreamRef streamRef,
                                   void *clientCallBackInfo, size_t numEvents,
                                   void *eventPaths,
                                   const FSEventStreamEventFlags eventFlags[],
                                   const FSEventStreamEventId eventIds[]) {
  char **paths = static_cast<char **>(eventPaths);

  JNIEventsDiffAwareness *info =
      static_cast<JNIEventsDiffAwareness *>(clientCallBackInfo);
  pthread_mutex_lock(&(info->mutex));
  for (int i = 0; i < numEvents; i++) {
    if ((eventFlags[i] & kFSEventStreamEventFlagMustScanSubDirs) != 0) {
      // Either we lost events or they were coalesced. Assume everything changed
      // and give up, which matches the fsevents documentation in that the
      // caller is expected to rescan the directory contents on its own.
      info->everything_changed = true;
      break;
    }
    info->paths.push_back(std::string(paths[i]));
  }
  pthread_mutex_unlock(&(info->mutex));
}

extern "C" JNIEXPORT void JNICALL
Java_com_google_devtools_build_lib_skyframe_MacOSXFsEventsDiffAwareness_create(
    JNIEnv *env, jobject fsEventsDiffAwareness, jobjectArray paths,
    jdouble latency) {
  // Create a FSEventStreamContext to pass around (env, fsEventsDiffAwareness)
  JNIEventsDiffAwareness *info = new JNIEventsDiffAwareness();

  FSEventStreamContext context;
  context.version = 0;
  context.info = static_cast<void *>(info);
  context.retain = NULL;
  context.release = NULL;
  context.copyDescription = NULL;

  // Create an CFArrayRef of CFStringRef from the Java array of String
  jsize length = env->GetArrayLength(paths);
  CFStringRef *pathsArray = new CFStringRef[length];
  for (int i = 0; i < length; i++) {
    jstring path = (jstring)env->GetObjectArrayElement(paths, i);
    const char *pathCStr = env->GetStringUTFChars(path, NULL);
    pathsArray[i] =
        CFStringCreateWithCString(NULL, pathCStr, kCFStringEncodingUTF8);
    env->ReleaseStringUTFChars(path, pathCStr);
  }
  CFArrayRef pathsToWatch =
      CFArrayCreate(NULL, (const void **)pathsArray, 1, NULL);
  delete[] pathsArray;
  info->stream = FSEventStreamCreate(
      NULL, &FsEventsDiffAwarenessCallback, &context, pathsToWatch,
      kFSEventStreamEventIdSinceNow, static_cast<CFAbsoluteTime>(latency),
      kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);

  // Save the info pointer to FSEventsDiffAwareness#nativePointer
  jbyteArray array = env->NewByteArray(sizeof(info));
  env->SetByteArrayRegion(array, 0, sizeof(info),
                          reinterpret_cast<const jbyte *>(&info));
  jclass clazz = env->GetObjectClass(fsEventsDiffAwareness);
  jfieldID fid = env->GetFieldID(clazz, "nativePointer", "J");
  env->SetLongField(fsEventsDiffAwareness, fid, reinterpret_cast<jlong>(info));
}

JNIEventsDiffAwareness *GetInfo(JNIEnv *env, jobject fsEventsDiffAwareness) {
  jclass clazz = env->GetObjectClass(fsEventsDiffAwareness);
  jfieldID fid = env->GetFieldID(clazz, "nativePointer", "J");
  jlong field = env->GetLongField(fsEventsDiffAwareness, fid);
  return reinterpret_cast<JNIEventsDiffAwareness *>(field);
}

}  // namespace

extern "C" JNIEXPORT void JNICALL
Java_com_google_devtools_build_lib_skyframe_MacOSXFsEventsDiffAwareness_run(
    JNIEnv *env, jobject fsEventsDiffAwareness, jobject listening) {
  JNIEventsDiffAwareness *info = GetInfo(env, fsEventsDiffAwareness);
  info->runLoop = CFRunLoopGetCurrent();
  FSEventStreamScheduleWithRunLoop(info->stream, info->runLoop,
                                   kCFRunLoopDefaultMode);
  FSEventStreamStart(info->stream);

  jclass countDownLatchClass = env->GetObjectClass(listening);
  jmethodID countDownMethod =
      env->GetMethodID(countDownLatchClass, "countDown", "()V");
  env->CallVoidMethod(listening, countDownMethod);
  CFRunLoopRun();
}

extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_google_devtools_build_lib_skyframe_MacOSXFsEventsDiffAwareness_poll(
    JNIEnv *env, jobject fsEventsDiffAwareness) {
  JNIEventsDiffAwareness *info = GetInfo(env, fsEventsDiffAwareness);
  pthread_mutex_lock(&(info->mutex));

  jobjectArray result;
  if (info->everything_changed) {
    result = NULL;
  } else {
    jclass classString = env->FindClass("java/lang/String");
    result = env->NewObjectArray(info->paths.size(), classString, NULL);
    int i = 0;
    for (auto it = info->paths.begin(); it != info->paths.end(); it++, i++) {
      env->SetObjectArrayElement(result, i, env->NewStringUTF(it->c_str()));
    }
  }

  info->everything_changed = false;
  info->paths.clear();

  pthread_mutex_unlock(&(info->mutex));
  return result;
}

extern "C" JNIEXPORT void JNICALL
Java_com_google_devtools_build_lib_skyframe_MacOSXFsEventsDiffAwareness_doClose(
    JNIEnv *env, jobject fsEventsDiffAwareness) {
  JNIEventsDiffAwareness *info = GetInfo(env, fsEventsDiffAwareness);
  CFRunLoopStop(info->runLoop);
  FSEventStreamStop(info->stream);
  FSEventStreamUnscheduleFromRunLoop(info->stream, info->runLoop,
                                     kCFRunLoopDefaultMode);
  FSEventStreamInvalidate(info->stream);
  FSEventStreamRelease(info->stream);
  delete info;
}
