// 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/common/condition_variable.h"
#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/queue.h"
#include "starboard/memory.h"
#include "starboard/once.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;
}
