/*
 * Copyright 2016 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 "cobalt/browser/memory_tracker_tool.h"

#include <map>
#include <string>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"

#if defined(OS_STARBOARD)
#include "nb/analytics/memory_tracker.h"
#include "nb/analytics/memory_tracker_impl.h"
#include "nb/scoped_ptr.h"
#include "nb/simple_thread.h"
#endif

namespace cobalt {
namespace browser {

#if !defined(OS_STARBOARD)
// A dummy implementation.
scoped_ptr<MemoryTrackerTool> CreateMemoryTrackerTool(const std::string&) {
  DLOG(INFO)
      << "Memory tracker tool is not enabled on non-starboard builds.";
  MemoryTrackerTool* null_ptr = NULL;
  return scoped_ptr<MemoryTrackerTool>(null_ptr);
}

#else  // defined(OS_STARBOARD)

namespace {
enum SwitchEnum {
  kNull,
  kStartup,
  kContinuousPrinter,
};

struct SwitchVal {
  SwitchVal() : help_msg(), enum_value(kNull) {}
  SwitchVal(const SwitchVal& other)
    : tool_name(other.tool_name), help_msg(other.help_msg),
      enum_value(other.enum_value) {}
  SwitchVal(const char* name, const char* msg, SwitchEnum val)
    : tool_name(name), help_msg(msg), enum_value(val) {}

  std::string tool_name;
  std::string help_msg;
  SwitchEnum enum_value;
};

}  // namespace.

class MemoryTrackerThreadImpl : public MemoryTrackerTool {
 public:
  explicit MemoryTrackerThreadImpl(nb::SimpleThread* ptr)
    : thread_ptr_(ptr) {
  }

  virtual ~MemoryTrackerThreadImpl() OVERRIDE {}
  scoped_ptr<nb::SimpleThread> thread_ptr_;
};

scoped_ptr<MemoryTrackerTool> CreateMemoryTrackerTool(
    const std::string& command_arg) {
  // The command line switch for memory_tracker was used. Look into the args
  // and determine the mode that the memory_tracker should be used for.
  using nb::analytics::MemoryTrackerPrintThread;
  using nb::analytics::MemoryTracker;

  // The map is used to
  // 1) Resolve the string to an enum.
  // 2) Print a useful help method of all known memory_tracker modes.
  typedef std::map<std::string, SwitchVal> SwitchMap;

  SwitchVal startup_tool(
    "startup",
    "Records high-frequency memory metrics for the first 60 "
    "seconds of program launch and then dumps it out in CSV format "
    "to stdout.",
    kStartup);

  SwitchVal continuous_printer_tool(
    "continuous_printer",
    "Once every second the memory state is dumped to stdout.",
    kContinuousPrinter);

  SwitchMap switch_map;
  switch_map[startup_tool.tool_name] = startup_tool;
  switch_map[continuous_printer_tool.tool_name] = continuous_printer_tool;

  // FAST OUT - is a thread type not selected? Then print out a help menu
  // and request that the app should shut down.
  SwitchMap::const_iterator found_it = switch_map.find(command_arg);
  if (found_it == switch_map.end()) {
    // Error, tell the user what to do instead and then exit.
    std::stringstream ss;
    ss << "\nNo memory tracker tool selected so help has been invoked:\n";
    ss << "Memory Tracker help:\n";
    for (SwitchMap::const_iterator it = switch_map.begin();
      it != switch_map.end(); ++it) {
        const std::string& name = it->first;
        const SwitchVal& val = it->second;
        ss << "    memory_tracker="
          << name << " " << "\"" << val.help_msg << "\"\n";
    }
    ss << "\n";
    SbLogRaw(ss.str().c_str());
    ss.str("");  // Clears the contents of stringstream.
    SbLogFlush();

    // Try and turn off all logging so that the stdout is less likely to be
    // polluted by interleaving output.
    logging::SetMinLogLevel(INT_MAX);
    // SbThreadSleep wants microseconds. We sleep here so that the user can
    // read the help message before the engine starts up again and the
    // fills the output with more logging text.
    const SbTime four_seconds = 4000 * kSbTimeMillisecond;
    SbThreadSleep(four_seconds);

    found_it = switch_map.find(continuous_printer_tool.tool_name);

    ss << "Defaulting to tool: " << found_it->first << "\n";
    SbLogRaw(ss.str().c_str());
    SbLogFlush();
    // One more help message and 1-second pause. Then continue on with the
    // execution as normal.
    const SbTime one_second = 1000 * kSbTimeMillisecond;
    SbThreadSleep(one_second);
  }

  // Okay we have been resolved to use a memory tracker in some way.
  DLOG(INFO) << "\n\nUsing MemoryTracking=" << found_it->first << "\n";

  MemoryTracker* memory_tracker = MemoryTracker::Get();
  memory_tracker->InstallGlobalTrackingHooks();

  scoped_ptr<nb::SimpleThread> thread_ptr;
  const SwitchVal& value = found_it->second;
  switch (value.enum_value) {
    case kNull: {
      SB_NOTREACHED();
      break;
    }
    case kStartup: {
      nb::scoped_ptr<nb::analytics::MemoryTrackerPrintCSVThread> ptr =
          CreateDebugPrintCSVThread(memory_tracker,
                                    1000,         // Sample once a second.
                                    60 * 1000);   // Output after 60 seconds.
      // Create a thread that will gather memory metrics for startup.
      thread_ptr.reset(ptr.release());
      break;
    }
    case kContinuousPrinter: {
      nb::scoped_ptr<MemoryTrackerPrintThread> ptr =
          CreateDebugPrintThread(memory_tracker);

      // Create a thread that will continuously report memory use.
      thread_ptr.reset(ptr.release());
      break;
    }

    default: {
      SB_NOTREACHED() << "Unhandled case.";
      break;
    }
  }
  // Wrap the tool up in MemoryTrackerThreadImpl.
  return scoped_ptr<MemoryTrackerTool>(
      new MemoryTrackerThreadImpl(thread_ptr.release()));
}

#endif  // defined(OS_STARBOARD)

}  // namespace browser
}  // namespace cobalt
