// 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 <stddef.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::NumberToString(var.value.as_int);
    case PP_VARTYPE_DOUBLE:
      return base::NumberToString(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();

      base::ReplaceSubstringsAfterOffset(
          &result, 0, base::StringPiece("\0", 1), "\\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; }

V8ObjectVar* Var::AsV8ObjectVar() { 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_t id = GetOrCreateVarID();
  if (!id)
    return PP_MakeNull();

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

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

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

Var::~Var() {}

int32_t 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_t 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_t 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_t>(var.size()));
}

// static
PP_Var StringVar::StringToPPVar(const char* data, uint32_t 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
