/*
 * 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 "starboard/client_porting/poem/string_leaks_poem.h"

#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/common/string.h"
#include "starboard/once.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
