/*
 * Copyright 2017 Google Inc. 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 <algorithm>
#include <string>
#include <vector>

#include "nb/rewindable_vector.h"
#include "nb/simple_profiler.h"
#include "nb/thread_local_object.h"
#include "starboard/atomic.h"
#include "starboard/once.h"
#include "starboard/string.h"
#include "starboard/time.h"

namespace nb {
namespace {

class SimpleProfilerManager {
 public:
  struct Entry {
    Entry() : name(nullptr), time_delta(0), indent_value(0) {}
    Entry(const char* n, SbTimeMonotonic dt, int ind)
        : name(n), time_delta(dt), indent_value(ind) {}
    Entry(const Entry& e) = default;
    const char* name;
    SbTimeMonotonic time_delta;
    int indent_value;
  };

  using MessageHandlerFunction = SimpleProfiler::MessageHandlerFunction;
  using ClockFunction = SimpleProfiler::ClockFunction;
  SimpleProfilerManager()
      : default_enabled_(true), message_handler_(nullptr),
        clock_function_(nullptr) {}

  int BeginInstance(const char* name) {
    Data& d = ThreadLocal();
    if (!d.enable_flag) {
      return -1;
    }
    SbTimeMonotonic now = NowTime();
    // SbAtomicMemoryBarrier() to Keep order of operations so clock doesn't
    // get sampled out of order.
    SbAtomicMemoryBarrier();
    d.profiles.emplace_back(name, now, d.instance_count);
    ++d.instance_count;
    return d.profiles.size() - 1;
  }

  void Output(const Entry& entry, std::stringstream* sstream) {
    for (auto i = 0; i < entry.indent_value; ++i) {
      (*sstream) << ' ';
    }
    (*sstream) << entry.name << ": " << entry.time_delta << "us\n";
  }

  void FinishInstance(int index) {
    Data& d = ThreadLocal();
    if (!d.enable_flag || index < 0) {
      return;
    }

    --d.instance_count;
    Entry& entry = d.profiles[static_cast<size_t>(index)];
    entry.time_delta = NowTime() - entry.time_delta;
    // SbAtomicMemoryBarrier() to Keep order of operations so clock doesn't
    // get sampled out of order.
    SbAtomicMemoryBarrier();

    if (d.instance_count == 0) {
      std::stringstream ss;
      for (auto it = d.profiles.begin(); it != d.profiles.end(); ++it) {
        Output(*it, &ss);
      }
      d.profiles.clear();
      HandleMessage(ss.str());
    }
  }
  bool ThreadLocalEnabled() { return ThreadLocal().enable_flag; }
  void SetThreadLocalEnabled(bool value) {
    Data& d = ThreadLocal();
    d.enable_flag = value;
    d.enable_flag_set = true;
  }

  bool IsEnabled() const {
    const Data& d = ThreadLocal();
    if (d.enable_flag_set) {
      return d.enable_flag;
    }
    return default_enabled_;
  }
  void SetDefaultEnabled(bool value) { default_enabled_ = value; }

  void SetMessageHandler(MessageHandlerFunction handler) {
    message_handler_ = handler;
  }

  void SetClockFunction(ClockFunction fcn) {
    clock_function_ = fcn;
  }

  SbTimeMonotonic NowTime() {
    if (!clock_function_) {
      return SbTimeGetMonotonicNow();
    } else {
      return clock_function_();
    }
  }

 private:
  struct Data {
    bool enable_flag = true;
    bool enable_flag_set = false;
    int instance_count = 0;
    std::vector<Entry> profiles;
  };

  void HandleMessage(const std::string& str) {
    if (message_handler_) {
      message_handler_(str.c_str());
    } else {
      SbLogRaw(str.c_str());
    }
  }

  Data& ThreadLocal() { return *thread_local_.GetOrCreate(); }
  const Data& ThreadLocal() const { return *thread_local_.GetOrCreate(); }
  mutable nb::ThreadLocalObject<Data> thread_local_;
  bool default_enabled_;
  MessageHandlerFunction message_handler_;
  ClockFunction clock_function_;
};

SB_ONCE_INITIALIZE_FUNCTION(SimpleProfilerManager, GetSimpleProfilerManager);

}  // namespace

SimpleProfiler::EnableScope::EnableScope(bool enabled) {
  SimpleProfilerManager* mgr = GetSimpleProfilerManager();
  prev_enabled_ = mgr->ThreadLocalEnabled();
  mgr->SetThreadLocalEnabled(enabled);
}

SimpleProfiler::EnableScope::~EnableScope() {
  GetSimpleProfilerManager()->SetThreadLocalEnabled(prev_enabled_);
}

SimpleProfiler::SimpleProfiler(const char* name) {
  momento_index_ = GetSimpleProfilerManager()->BeginInstance(name);
}

SimpleProfiler::~SimpleProfiler() {
  GetSimpleProfilerManager()->FinishInstance(momento_index_);
}

void SimpleProfiler::SetEnabledByDefault(bool value) {
  GetSimpleProfilerManager()->SetDefaultEnabled(value);
}

bool SimpleProfiler::IsEnabled() {
  return GetSimpleProfilerManager()->IsEnabled();
}

void SimpleProfiler::SetLoggingFunction(MessageHandlerFunction fcn) {
  GetSimpleProfilerManager()->SetMessageHandler(fcn);
}

void SimpleProfiler::SetClockFunction(ClockFunction fcn) {
  GetSimpleProfilerManager()->SetClockFunction(fcn);
}

}  // namespace nb
