// Copyright 2012 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/media/base/shell_data_source_reader.h"

#include "starboard/types.h"

namespace cobalt {
namespace media {

const int ShellDataSourceReader::kReadError = DataSource::kReadError;

ShellDataSourceReader::ShellDataSourceReader()
    : data_source_(NULL),
      blocking_read_event_(false, false),
      file_size_(-1),
      read_has_failed_(false),
      last_bytes_read_(0) {}

ShellDataSourceReader::~ShellDataSourceReader() {}

void ShellDataSourceReader::SetDataSource(DataSource* data_source) {
  DCHECK(data_source);
  data_source_ = data_source;
}

// currently only single-threaded reads supported
int ShellDataSourceReader::BlockingRead(int64 position, int size, uint8* data) {
  // read failures are unrecoverable, all subsequent reads will also fail
  if (read_has_failed_) {
    return kReadError;
  }

  // check bounds of read at or past EOF
  if (file_size_ >= 0 && position >= file_size_) {
    return 0;
  }

  int total_bytes_read = 0;
  while (size > 0 && !read_has_failed_) {
    {
      base::AutoLock auto_lock(lock_);
      if (!data_source_) {
        break;
      }
      data_source_->Read(
          position, size, data,
          base::Bind(&ShellDataSourceReader::BlockingReadCompleted, this));
    }

    // wait for callback on read completion
    blocking_read_event_.Wait();

    if (last_bytes_read_ == DataSource::kReadError) {
      // make all future reads fail
      read_has_failed_ = true;
      return kReadError;
    }

    DCHECK_LE(last_bytes_read_, size);
    if (last_bytes_read_ > size) {
      // make all future reads fail
      read_has_failed_ = true;
      return kReadError;
    }

    // Avoid entering an endless loop here.
    if (last_bytes_read_ == 0) break;

    total_bytes_read += last_bytes_read_;
    position += last_bytes_read_;
    size -= last_bytes_read_;
    data += last_bytes_read_;
  }

  if (read_has_failed_) {
    return kReadError;
  }
  return total_bytes_read;
}

void ShellDataSourceReader::Stop() {
  if (data_source_) {
    data_source_->Stop();

    base::AutoLock auto_lock(lock_);
    data_source_ = NULL;
  }
}

void ShellDataSourceReader::BlockingReadCompleted(int bytes_read) {
  last_bytes_read_ = bytes_read;
  // wake up blocked thread
  blocking_read_event_.Signal();
}

int64 ShellDataSourceReader::FileSize() {
  if (file_size_ == -1) {
    base::AutoLock auto_lock(lock_);
    if (data_source_ && !data_source_->GetSize(&file_size_)) {
      file_size_ = -1;
    }
  }
  return file_size_;
}

}  // namespace media
}  // namespace cobalt
