// 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;
    } else if ((eventFlags[i] & kFSEventStreamEventFlagItemIsDir) != 0 &&
        (eventFlags[i] & kFSEventStreamEventFlagItemRenamed) != 0) {
      // A directory was renamed. When this happens, fsevents may or may not
      // give us individual events about which files changed underneath, which
      // means we have to rescan the directories in order to know what changed.
      //
      // The problem is that we cannot rescan the source of the move to discover
      // which files "disappeared"... so we have no choice but to rescan
      // everything. Well, in theory, we could try to track directory inodes and
      // using those to guess which files within them moved... but that'd be way
      // too much complexity for this rather-uncommon use case.
      info->everything_changed = true;
      break;
    } else {
      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;
}
