/*
 * 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/web/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)
    : web::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) {
  web::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<web::Event> event = new web::Event(event_name);
  event->set_target(this);
  event_queue_->Enqueue(event);
}

}  // namespace dom
}  // namespace cobalt
