// 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 {

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) {
  // Clamp out of range start/end to valid indices.
  if (start > source_length) {
    start = source_length;
  }
  if (end > source_length) {
    end = source_length;
  }

  // Wrap around negative indices.
  if (start < 0) {
    start = source_length + start;
  }
  if (end < 0) {
    end = source_length + end;
  }

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

ArrayBuffer::~ArrayBuffer() {}

}  // namespace dom
}  // namespace cobalt
