// Copyright 2016 The Cobalt 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 "starboard/client_porting/pr_starboard/pr_starboard.h"

#include "nb/thread_local_object.h"
#include "starboard/condition_variable.h"
#include "starboard/log.h"
#include "starboard/memory.h"
#include "starboard/mutex.h"
#include "starboard/once.h"
#include "starboard/queue.h"
#include "starboard/thread.h"
#include "starboard/time.h"
#include "starboard/types.h"

namespace {

typedef starboard::Queue<PRThread*> SetupSignalQueue;
typedef nb::ThreadLocalObject<PRThread> ThreadLocalPRThread;
SB_ONCE_INITIALIZE_FUNCTION(ThreadLocalPRThread,
                            g_local_pr_thread);

// Utility function to convert a PRInterval to signed 64 bit integer
// microseconds.
int64_t PR_IntervalToMicrosecondsInt64(PRIntervalTime ticks) {
  uint32_t microseconds_as_uint32 = PR_IntervalToMicroseconds(ticks);
  int64_t microseconds_as_int64 = static_cast<int64_t>(microseconds_as_uint32);
  return microseconds_as_int64;
}

// Struct to bundle up arguments to be passed into SbThreadCreate.
struct ThreadEntryPointWrapperContext {
  ThreadEntryPointWrapperContext(void* pr_context,
                                 PRThreadEntryPoint pr_entry_point,
                                 SetupSignalQueue* setup_signal_queue)
      : pr_context(pr_context),
        pr_entry_point(pr_entry_point),
        setup_signal_queue(setup_signal_queue) {}
  void* pr_context;
  PRThreadEntryPoint pr_entry_point;
  SetupSignalQueue* setup_signal_queue;
};

void* ThreadEntryPointWrapper(void* context_as_void_pointer) {
  ThreadEntryPointWrapperContext* context =
      reinterpret_cast<ThreadEntryPointWrapperContext*>(
          context_as_void_pointer);
  void* pr_context = context->pr_context;
  PRThreadEntryPoint pr_entry_point = context->pr_entry_point;
  SetupSignalQueue* setup_signal_queue = context->setup_signal_queue;

  delete context;

  SB_DCHECK(g_local_pr_thread()->GetIfExists() == NULL);
  PRThread* pr_thread = g_local_pr_thread()->GetOrCreate(SbThreadGetCurrent());
  SB_DCHECK(pr_thread);
  setup_signal_queue->Put(pr_thread);
  pr_entry_point(pr_context);

  return NULL;
}

}  // namespace

PRLock* PR_NewLock() {
  PRLock* lock = new PRLock();
  if (!SbMutexCreate(lock)) {
    delete lock;
    return NULL;
  }
  return lock;
}

void PR_DestroyLock(PRLock* lock) {
  SB_DCHECK(lock);
  SbMutexDestroy(lock);
  delete lock;
}

PRCondVar* PR_NewCondVar(PRLock* lock) {
  SB_DCHECK(lock);
  PRCondVar* cvar = new PRCondVar();
  if (!SbConditionVariableCreate(&cvar->sb_condition_variable, lock)) {
    delete cvar;
    return NULL;
  }
  cvar->lock = lock;
  return cvar;
}

void PR_DestroyCondVar(PRCondVar* cvar) {
  SbConditionVariableDestroy(&cvar->sb_condition_variable);
  delete cvar;
}

PRStatus PR_WaitCondVar(PRCondVar* cvar, PRIntervalTime timeout) {
  SbConditionVariableResult result;
  if (timeout == PR_INTERVAL_NO_WAIT) {
    result = SbConditionVariableWaitTimed(&cvar->sb_condition_variable,
                                          cvar->lock, 0);
  } else if (timeout == PR_INTERVAL_NO_TIMEOUT) {
    result = SbConditionVariableWait(&cvar->sb_condition_variable, cvar->lock);
  } else {
    int64_t microseconds = PR_IntervalToMicrosecondsInt64(timeout);
    result = SbConditionVariableWaitTimed(&cvar->sb_condition_variable,
                                          cvar->lock, microseconds);
  }
  return pr_starboard::ToPRStatus(result != kSbConditionVariableFailed);
}

PRThread* PR_GetCurrentThread() {
  return g_local_pr_thread()->GetOrCreate(SbThreadGetCurrent());
}

uint32_t PR_snprintf(char* out, uint32_t outlen, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  uint32_t ret = PR_vsnprintf(out, outlen, fmt, args);
  va_end(args);
  return ret;
}

PRThread* PR_CreateThread(PRThreadType type,
                          PRThreadEntryPoint start,
                          void* arg,
                          PRThreadPriority priority,
                          PRThreadScope scope,
                          PRThreadState state,
                          PRUint32 stackSize) {
  int64_t sb_stack_size = static_cast<int64_t>(stackSize);

  SbThreadPriority sb_priority;
  switch (priority) {
    case PR_PRIORITY_LOW:
      sb_priority = kSbThreadPriorityLow;
      break;
    case PR_PRIORITY_NORMAL:
      sb_priority = kSbThreadPriorityNormal;
      break;
    case PR_PRIORITY_HIGH:
      sb_priority = kSbThreadPriorityHigh;
      break;
    case PR_PRIORITY_LAST:
      sb_priority = kSbThreadPriorityHighest;
      break;
    default:
      sb_priority = kSbThreadNoPriority;
  }

  SbThreadAffinity sb_affinity = kSbThreadNoAffinity;

  SB_DCHECK(state == PR_JOINABLE_THREAD || state == PR_UNJOINABLE_THREAD);
  bool sb_joinable = (state == PR_JOINABLE_THREAD);

  // A queue that serves two purposes.  The first is that it is a way for our
  // child thread to signal to us that it is done with its wrapper level
  // setup, and that we can safely return.  The second, is that it is a
  // channel for it to pass us the address of the child thread's |PRThread|
  // object.
  SetupSignalQueue setup_signal_queue;

  // This heap allocated context object is freed after the initial setup of
  // |ThreadEntryPointWrapper| is complete, right before the nspr level entry
  // point is run.
  ThreadEntryPointWrapperContext* context =
      new ThreadEntryPointWrapperContext(arg, start, &setup_signal_queue);

  SbThreadCreate(sb_stack_size, sb_priority, sb_affinity, sb_joinable, NULL,
                 ThreadEntryPointWrapper, context);

  // Now we must wait for the setup section of |ThreadEntryPointWrapper| to
  // run and pass us the initialized |pr_thread|.
  PRThread* child_pr_thread = setup_signal_queue.Get();
  SB_DCHECK(child_pr_thread);
  SB_DCHECK(SbThreadIsValid(child_pr_thread->sb_thread));

  return child_pr_thread;
}

PRStatus PR_CallOnceWithArg(PRCallOnceType* once,
                            PRCallOnceWithArgFN func,
                            void* arg) {
  SB_NOTREACHED() << "Not implemented";
  return PR_FAILURE;
}

PRStatus PR_NewThreadPrivateIndex(PRTLSIndex* newIndex,
                                  PRThreadPrivateDTOR destructor) {
  SbThreadLocalKey key = SbThreadCreateLocalKey(destructor);
  if (!SbThreadIsValidLocalKey(key)) {
    return pr_starboard::ToPRStatus(false);
  }
  *newIndex = key;
  return pr_starboard::ToPRStatus(true);
}

PRIntervalTime PR_MillisecondsToInterval(PRUint32 milli) {
  PRUint64 tock = static_cast<PRUint64>(milli);
  PRUint64 msecPerSec = static_cast<PRInt64>(PR_MSEC_PER_SEC);
  PRUint64 rounding = static_cast<PRInt64>(PR_MSEC_PER_SEC >> 1);
  PRUint64 tps = static_cast<PRInt64>(PR_TicksPerSecond());

  tock *= tps;
  tock += rounding;
  tock /= msecPerSec;

  PRUint64 ticks = static_cast<PRUint64>(tock);
  return ticks;
}

PRUint32 PR_IntervalToMicroseconds(PRIntervalTime ticks) {
  PRUint64 tock = static_cast<PRInt64>(ticks);
  PRUint64 usecPerSec = static_cast<PRInt64>(PR_USEC_PER_SEC);
  PRUint64 tps = static_cast<PRInt64>(PR_TicksPerSecond());
  PRUint64 rounding = static_cast<PRUint64>(tps) >> 1;

  tock *= usecPerSec;
  tock += rounding;
  tock /= tps;

  PRUint32 micro = static_cast<PRUint32>(tock);
  return micro;
}
