// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/shared_impl/var.h"

#include <limits>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/var_tracker.h"

namespace ppapi {

// Var -------------------------------------------------------------------------

// static
std::string Var::PPVarToLogString(PP_Var var) {
  switch (var.type) {
    case PP_VARTYPE_UNDEFINED:
      return "[Undefined]";
    case PP_VARTYPE_NULL:
      return "[Null]";
    case PP_VARTYPE_BOOL:
      return var.value.as_bool ? "[True]" : "[False]";
    case PP_VARTYPE_INT32:
      return base::IntToString(var.value.as_int);
    case PP_VARTYPE_DOUBLE:
      return base::DoubleToString(var.value.as_double);
    case PP_VARTYPE_STRING: {
      StringVar* string(StringVar::FromPPVar(var));
      if (!string)
        return "[Invalid string]";

      // Since this is for logging, escape NULLs, truncate length.
      std::string result;
      const size_t kTruncateAboveLength = 128;
      if (string->value().size() > kTruncateAboveLength)
        result = string->value().substr(0, kTruncateAboveLength) + "...";
      else
        result = string->value();

      std::string null;
      null.push_back(0);
      ReplaceSubstringsAfterOffset(&result, 0, null, "\\0");
      return result;
    }
    case PP_VARTYPE_OBJECT:
      return "[Object]";
    case PP_VARTYPE_ARRAY:
      return "[Array]";
    case PP_VARTYPE_DICTIONARY:
      return "[Dictionary]";
    case PP_VARTYPE_ARRAY_BUFFER:
      return "[Array buffer]";
    case PP_VARTYPE_RESOURCE: {
      ResourceVar* resource(ResourceVar::FromPPVar(var));
      if (!resource)
        return "[Invalid resource]";

      if (resource->IsPending()) {
        return base::StringPrintf("[Pending resource]");
      } else if (resource->GetPPResource()) {
        return base::StringPrintf("[Resource %d]", resource->GetPPResource());
      } else {
        return "[Null resource]";
      }
    }
    default:
      return "[Invalid var]";
  }
}

StringVar* Var::AsStringVar() { return NULL; }

ArrayBufferVar* Var::AsArrayBufferVar() { return NULL; }

NPObjectVar* Var::AsNPObjectVar() { return NULL; }

ProxyObjectVar* Var::AsProxyObjectVar() { return NULL; }

ArrayVar* Var::AsArrayVar() { return NULL; }

DictionaryVar* Var::AsDictionaryVar() { return NULL; }

ResourceVar* Var::AsResourceVar() { return NULL; }

PP_Var Var::GetPPVar() {
  int32 id = GetOrCreateVarID();
  if (!id)
    return PP_MakeNull();

  PP_Var result;
  result.type = GetType();
  result.padding = 0;
  result.value.as_id = id;
  return result;
}

int32 Var::GetExistingVarID() const { return var_id_; }

Var::Var() : var_id_(0) {}

Var::~Var() {}

int32 Var::GetOrCreateVarID() {
  VarTracker* tracker = PpapiGlobals::Get()->GetVarTracker();
  if (var_id_) {
    if (!tracker->AddRefVar(var_id_))
      return 0;
  } else {
    var_id_ = tracker->AddVar(this);
    if (!var_id_)
      return 0;
  }
  return var_id_;
}

void Var::AssignVarID(int32 id) {
  DCHECK(!var_id_);  // Must not have already been generated.
  var_id_ = id;
}

// StringVar -------------------------------------------------------------------

StringVar::StringVar() {}

StringVar::StringVar(const std::string& str) : value_(str) {}

StringVar::StringVar(const char* str, uint32 len) : value_(str, len) {}

StringVar::~StringVar() {}

StringVar* StringVar::AsStringVar() { return this; }

PP_VarType StringVar::GetType() const { return PP_VARTYPE_STRING; }

// static
PP_Var StringVar::StringToPPVar(const std::string& var) {
  return StringToPPVar(var.c_str(), static_cast<uint32>(var.size()));
}

// static
PP_Var StringVar::StringToPPVar(const char* data, uint32 len) {
  scoped_refptr<StringVar> str(new StringVar(data, len));
  if (!str.get() || !base::IsStringUTF8(str->value()))
    return PP_MakeNull();
  return str->GetPPVar();
}

// static
StringVar* StringVar::FromPPVar(PP_Var var) {
  if (var.type != PP_VARTYPE_STRING)
    return NULL;
  scoped_refptr<Var> var_object(
      PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
  if (!var_object.get())
    return NULL;
  return var_object->AsStringVar();
}

// static
PP_Var StringVar::SwapValidatedUTF8StringIntoPPVar(std::string* src) {
  scoped_refptr<StringVar> str(new StringVar);
  str->value_.swap(*src);
  return str->GetPPVar();
}

// ArrayBufferVar --------------------------------------------------------------

ArrayBufferVar::ArrayBufferVar() {}

ArrayBufferVar::~ArrayBufferVar() {}

ArrayBufferVar* ArrayBufferVar::AsArrayBufferVar() { return this; }

PP_VarType ArrayBufferVar::GetType() const { return PP_VARTYPE_ARRAY_BUFFER; }

// static
ArrayBufferVar* ArrayBufferVar::FromPPVar(PP_Var var) {
  if (var.type != PP_VARTYPE_ARRAY_BUFFER)
    return NULL;
  scoped_refptr<Var> var_object(
      PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
  if (!var_object.get())
    return NULL;
  return var_object->AsArrayBufferVar();
}

}  // namespace ppapi
