/*
 * Copyright (C) 2013 Google Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// Modifications 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/dom/source_buffer_list.h"

#include <algorithm>
#include <limits>

#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/event.h"

namespace cobalt {
namespace dom {

namespace {
// SourceBufferList usually contains 2 source buffers.
const int kSizeOfSourceBufferToReserveInitially = 2;
}  // namespace

SourceBufferList::SourceBufferList(script::EnvironmentSettings* settings,
                                   EventQueue* event_queue)
    : EventTarget(settings), event_queue_(event_queue) {
  DCHECK(event_queue_);
  source_buffers_.reserve(kSizeOfSourceBufferToReserveInitially);
}

SourceBufferList::~SourceBufferList() { DCHECK(source_buffers_.empty()); }

uint32 SourceBufferList::length() const {
  DCHECK_LE(source_buffers_.size(), std::numeric_limits<uint32>::max());
  return static_cast<uint32>(source_buffers_.size());
}

scoped_refptr<SourceBuffer> SourceBufferList::Item(uint32 index) const {
  if (index < source_buffers_.size()) {
    return source_buffers_[index];
  }
  return NULL;
}

void SourceBufferList::Add(const scoped_refptr<SourceBuffer>& source_buffer) {
  source_buffers_.push_back(source_buffer);
  ScheduleEvent(base::Tokens::addsourcebuffer());
}

void SourceBufferList::Insert(
    size_t position, const scoped_refptr<SourceBuffer>& source_buffer) {
  source_buffers_.insert(source_buffers_.begin() + position, source_buffer);
  ScheduleEvent(base::Tokens::addsourcebuffer());
}

void SourceBufferList::Remove(
    const scoped_refptr<SourceBuffer>& source_buffer) {
  SourceBuffers::iterator iter =
      std::find(source_buffers_.begin(), source_buffers_.end(), source_buffer);
  if (iter == source_buffers_.end()) {
    return;
  }

  source_buffers_.erase(iter);
  ScheduleEvent(base::Tokens::removesourcebuffer());
}

size_t SourceBufferList::Find(
    const scoped_refptr<SourceBuffer>& source_buffer) const {
  DCHECK(Contains(source_buffer));
  return std::distance(
      source_buffers_.begin(),
      std::find(source_buffers_.begin(), source_buffers_.end(), source_buffer));
}

bool SourceBufferList::Contains(
    const scoped_refptr<SourceBuffer>& source_buffer) const {
  return std::find(source_buffers_.begin(), source_buffers_.end(),
                   source_buffer) != source_buffers_.end();
}

void SourceBufferList::Clear() {
  source_buffers_.clear();
  ScheduleEvent(base::Tokens::removesourcebuffer());
}

void SourceBufferList::TraceMembers(script::Tracer* tracer) {
  EventTarget::TraceMembers(tracer);

  if (event_queue_) {
    event_queue_->TraceMembers(tracer);
  }
  for (const auto& source_buffer : source_buffers_) {
    tracer->Trace(source_buffer);
  }
}

void SourceBufferList::ScheduleEvent(base::Token event_name) {
  scoped_refptr<Event> event = new Event(event_name);
  event->set_target(this);
  event_queue_->Enqueue(event);
}

}  // namespace dom
}  // namespace cobalt
