// Copyright 2015 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/dom/array_buffer.h"

#include <algorithm>

#include "base/logging.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/script/javascript_engine.h"
#include "nb/memory_scope.h"

namespace cobalt {
namespace dom {

namespace {

int ClampIndex(int index, int length) {
  if (index < 0) {
    index = length + index;
  }
  index = std::max(index, 0);
  return std::min(index, length);
}

}  // namespace

ArrayBuffer::Data::Data(script::EnvironmentSettings* settings, size_t size)
    : allocator_(NULL), cache_(NULL), offloaded_(false), data_(NULL), size_(0) {
  Initialize(settings, size);
  if (data_) {
    memset(data_, 0, size);
  }
  if (cache_) {
    cache_->Register(this);
  }
}

ArrayBuffer::Data::Data(script::EnvironmentSettings* settings,
                        const uint8* data, size_t size)
    : allocator_(NULL), cache_(NULL), offloaded_(false), data_(NULL), size_(0) {
  Initialize(settings, size);
  DCHECK(data_);
  memcpy(data_, data, size);
  // Register() has to be called after copying the data as Register() will call
  // TryToOffload() which may delete the |data_| passed in that belongs to
  // another ArrayBuffer.
  if (cache_) {
    cache_->Register(this);
  }
}

ArrayBuffer::Data::Data(scoped_array<uint8> data, size_t size)
    : allocator_(NULL),
      cache_(NULL),
      offloaded_(false),
      data_(data.release()),
      size_(size) {
  DCHECK(data_);
}

ArrayBuffer::Data::~Data() {
  if (offloaded_) {
    allocator_->Free(data_);
  } else {
    delete[] data_;
  }
  if (cache_) {
    cache_->Unregister(this);
  }
}

uint8* ArrayBuffer::Data::data() const {
  if (cache_) {
    cache_->ReportUsage(this);
  }
  return data_;
}

bool ArrayBuffer::Data::Offload() {
  if (offloaded_) {
    return true;
  }
  if (!allocator_) {
    return false;
  }
  uint8* data = reinterpret_cast<uint8*>(allocator_->Allocate(size()));
  if (data) {
    memcpy(data, data_, size());
    delete[] data_;
    data_ = data;
    offloaded_ = true;
  }
  return offloaded_;
}

void ArrayBuffer::Data::Initialize(script::EnvironmentSettings* settings,
                                   size_t size) {
  TRACK_MEMORY_SCOPE("DOM");
  if (settings) {
    DOMSettings* dom_settings =
        base::polymorphic_downcast<dom::DOMSettings*>(settings);
    allocator_ = dom_settings->array_buffer_allocator();
    cache_ = dom_settings->array_buffer_cache();
    if (allocator_) {
      DCHECK(cache_);
    } else {
      DCHECK(!cache_);
    }
  }
  data_ = new uint8[size];
  size_ = size;
}

ArrayBuffer::Cache::Cache(size_t maximum_size_in_main_memory)
    : total_size_in_main_memory_(0),
      maximum_size_in_main_memory_(maximum_size_in_main_memory) {}

void ArrayBuffer::Cache::Register(Data* data) {
  total_size_in_main_memory_ += data->size();
  // Offload before push_back to ensure that the last one is always not
  // offloaded immediately.
  TryToOffload();
  datas_.push_back(data);
}

void ArrayBuffer::Cache::Unregister(Data* data) {
  DCHECK(std::find(datas_.begin(), datas_.end(), data) != datas_.end());
  datas_.erase(std::find(datas_.begin(), datas_.end(), data));
  if (!data->offloaded()) {
    DCHECK_GE(total_size_in_main_memory_, data->size());
    total_size_in_main_memory_ -= data->size();
  }
}

void ArrayBuffer::Cache::ReportUsage(const Data* data) {
  DCHECK(data);
  DCHECK(std::find(datas_.begin(), datas_.end(), data) != datas_.end());
  if (data->offloaded() || datas_.back() == data) {
    return;
  }
  // Move |data| to the end.
  datas_.erase(std::find(datas_.begin(), datas_.end(), data));
  datas_.push_back(const_cast<Data*>(data));
}

void ArrayBuffer::Cache::TryToOffload() {
  TRACK_MEMORY_SCOPE("DOM");
  if (total_size_in_main_memory_ <= maximum_size_in_main_memory_) {
    return;
  }
  std::vector<Data*>::iterator iter = datas_.begin();
  while (iter != datas_.end() &&
         total_size_in_main_memory_ > maximum_size_in_main_memory_) {
    if (!(*iter)->offloaded() && (*iter)->Offload()) {
      total_size_in_main_memory_ -= (*iter)->size();
    }
    ++iter;
  }
  if (total_size_in_main_memory_ > maximum_size_in_main_memory_) {
    LOG(WARNING) << "ArrayBuffer takes " << total_size_in_main_memory_
                 << " of main memory and cannot be offloaded";
  }
}

ArrayBuffer::ArrayBuffer(script::EnvironmentSettings* settings, uint32 length)
    : data_(settings, length) {
  // TODO: Once we can have a reliable way to pass the
  // EnvironmentSettings to HTMLMediaElement, we should make EnvironmentSettings
  // mandatory for creating ArrayBuffer in non-testing code.
  if (settings) {
    DOMSettings* dom_settings =
        base::polymorphic_downcast<dom::DOMSettings*>(settings);
    dom_settings->javascript_engine()->ReportExtraMemoryCost(data_.size());
  }
}

ArrayBuffer::ArrayBuffer(script::EnvironmentSettings* settings,
                         const uint8* data, uint32 length)
    : data_(settings, data, length) {
  // TODO: Make EnvironmentSettings mandatory for creating
  // ArrayBuffer in non-testing code.
  if (settings) {
    DOMSettings* dom_settings =
        base::polymorphic_downcast<dom::DOMSettings*>(settings);
    dom_settings->javascript_engine()->ReportExtraMemoryCost(data_.size());
  }
}

ArrayBuffer::ArrayBuffer(script::EnvironmentSettings* settings,
                         AllocationType allocation_type,
                         scoped_array<uint8> data, uint32 length)
    : data_(data.Pass(), length) {
  DCHECK_EQ(allocation_type, kFromHeap);
  // TODO: Make EnvironmentSettings mandatory for creating
  // ArrayBuffer in non-testing code.
  if (settings) {
    DOMSettings* dom_settings =
        base::polymorphic_downcast<dom::DOMSettings*>(settings);
    dom_settings->javascript_engine()->ReportExtraMemoryCost(data_.size());
  }
}

scoped_refptr<ArrayBuffer> ArrayBuffer::Slice(
    script::EnvironmentSettings* settings, int start, int end) const {
  TRACK_MEMORY_SCOPE("DOM");
  int clamped_start;
  int clamped_end;
  ClampRange(start, end, static_cast<int>(byte_length()), &clamped_start,
             &clamped_end);
  DCHECK_GE(clamped_end, clamped_start);
  size_t slice_size = static_cast<size_t>(clamped_end - clamped_start);
  return new ArrayBuffer(settings, data() + clamped_start,
                         static_cast<uint32>(slice_size));
}

void ArrayBuffer::ClampRange(int start, int end, int source_length,
                             int* clamped_start, int* clamped_end) {
  start = ClampIndex(start, source_length);
  end = ClampIndex(end, source_length);

  // Clamp the length of the new array to non-negative.
  if (end - start < 0) {
    end = start;
  }
  *clamped_start = start;
  *clamped_end = end;
}

ArrayBuffer::~ArrayBuffer() {}

}  // namespace dom
}  // namespace cobalt
