// Copyright 2017 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 "cobalt/browser/memory_tracker/tool/print_tool.h"

#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/threading/platform_thread.h"
#include "cobalt/base/c_val.h"
#include "cobalt/browser/memory_tracker/tool/util.h"
#include "nb/analytics/memory_tracker.h"
#include "nb/analytics/memory_tracker_helpers.h"
#include "starboard/log.h"
#include "starboard/types.h"

namespace cobalt {
namespace browser {
namespace memory_tracker {

using nb::analytics::AllocationGroup;

class PrintTool::CvalsMap {
 public:
  typedef base::CVal<base::cval::SizeInBytes> CValType;

  ~CvalsMap() {
    while (!map_.empty()) {
      MapCvals::iterator it = map_.begin();
      delete it->second;
      map_.erase(it);
    }
  }

  void Update(const std::string& name, size_t value) {
    std::string cval_name = GetCvalName(name);
    CValType*& val = map_[cval_name];
    if (!val) {
      // Create if not found.
      val = new CValType(cval_name, 0,
                         "Automatically generated by the "
                         "browser::memory_tracker system.");
    }
    (*val) = value;
  }

  static std::string GetCvalName(const std::string& name) {
    std::stringstream ss;
    ss << "Memory.Scope." << name;
    return ss.str();
  }

 private:
  typedef std::map<std::string, CValType*> MapCvals;
  MapCvals map_;
};

PrintTool::PrintTool() : cvals_map_(new CvalsMap) {}

PrintTool::~PrintTool() {}

void PrintTool::Run(Params* params) {
  const std::string kSeparator =
      "--------------------------------------------------";

  while (!params->finished()) {
    std::vector<const AllocationGroup*> vector_output;
    params->memory_tracker()->GetAllocationGroups(&vector_output);

    typedef std::map<std::string, const AllocationGroup*> Map;
    typedef Map::const_iterator MapIt;

    Map output;
    for (size_t i = 0; i < vector_output.size(); ++i) {
      const AllocationGroup* group = vector_output[i];
      output[group->name()] = group;
    }

    int32 num_allocs = 0;
    int64 total_bytes = 0;

    struct F {
      static void PrintRow(std::stringstream* ss, const std::string& v1,
                           const std::string& v2, const std::string& v3) {
        ss->width(25);
        *ss << std::left << v1;
        ss->width(13);
        *ss << std::right << v2 << "  ";
        ss->width(10);
        *ss << std::right << v3 << "\n";
      }
    };

    if (params->memory_tracker()->IsMemoryTrackingEnabled()) {
      // If this isn't true then it would cause an infinite loop. The
      // following will likely crash.
      SB_DCHECK(false) << "Unexpected, memory tracking should be disabled.";
    }

    std::stringstream ss;

    ss << kNewLine;
    ss << "TimeNow " << params->TimeInMinutesString()
       << " (minutes):" << kNewLine << kNewLine;

    ss << kSeparator << kNewLine;
    nb::analytics::MemoryStats memstats =
        nb::analytics::GetProcessMemoryStats();

    F::PrintRow(&ss, "MALLOC STAT", "IN USE BYTES", "");
    ss << kSeparator << kNewLine;
    F::PrintRow(&ss, "Total CPU Reserved",
                NumberFormatWithCommas(memstats.total_cpu_memory), "");

    F::PrintRow(&ss, "Total CPU Used",
                NumberFormatWithCommas(memstats.used_cpu_memory), "");

    F::PrintRow(&ss, "Total GPU Reserved",
                NumberFormatWithCommas(memstats.total_gpu_memory), "");

    F::PrintRow(&ss, "Total GPU Used",
                NumberFormatWithCommas(memstats.used_gpu_memory), "");

    ss << kSeparator << kNewLine << kNewLine;

    ss << kSeparator << kNewLine;
    F::PrintRow(&ss, "MEMORY REGION", "IN USE BYTES", "NUM ALLOCS");
    ss << kSeparator << kNewLine;

    for (MapIt it = output.begin(); it != output.end(); ++it) {
      const AllocationGroup* group = it->second;
      if (!group) {
        continue;
      }

      int32 num_group_allocs = -1;
      int64 total_group_bytes = -1;

      group->GetAggregateStats(&num_group_allocs, &total_group_bytes);
      SB_DCHECK(-1 != num_group_allocs);
      SB_DCHECK(-1 != total_group_bytes);

      cvals_map_->Update(group->name(), static_cast<size_t>(total_group_bytes));

      num_allocs += num_group_allocs;
      total_bytes += total_group_bytes;

      F::PrintRow(&ss, it->first, NumberFormatWithCommas(total_group_bytes),
                  NumberFormatWithCommas(num_group_allocs));
    }

    cvals_map_->Update("Total", static_cast<size_t>(total_bytes));

    ss << kNewLine;

    F::PrintRow(&ss, "Total (in groups above)",
                NumberFormatWithCommas(total_bytes),
                NumberFormatWithCommas(num_allocs));

    ss << kSeparator << kNewLine;
    ss << kNewLine << kNewLine;

    params->logger()->Output(ss.str().c_str());
    // Output once every 5 seconds.
    base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(5));
  }
}

std::string PrintTool::tool_name() const { return "MemoryTrackerPrintThread"; }

}  // namespace memory_tracker
}  // namespace browser
}  // namespace cobalt
