// 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/loader/embedded_fetcher.h"

#include <algorithm>

#include "base/bind.h"
#include "base/callback.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
#include "cobalt/loader/embedded_resources.h"  // Generated.

namespace cobalt {
namespace loader {

namespace {
bool EmbeddedURLToKey(const GURL& url, std::string* key) {
  DCHECK(url.is_valid() && url.SchemeIs(kEmbeddedScheme));
  *key = url.path();
  DCHECK_EQ('/', (*key)[0]);
  DCHECK_EQ('/', (*key)[1]);
  (*key).erase(0, 2);
  return !key->empty();
}
}  // namespace

const char kEmbeddedScheme[] = "h5vcc-embedded";

EmbeddedFetcher::EmbeddedFetcher(const GURL& url,
                                 const csp::SecurityCallback& security_callback,
                                 Handler* handler, const Options& options)
    : Fetcher(handler),
      url_(url),
      security_callback_(security_callback),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
  // Embedded assets are available in-memory and can be loaded synchronously.
  Fetch(options);
}

EmbeddedFetcher::~EmbeddedFetcher() {}

void EmbeddedFetcher::Fetch(const Options& options) {
  if (!IsAllowedByCsp()) {
    std::string msg(base::StringPrintf("URL %s rejected by security policy.",
                                       url_.spec().c_str()));
    handler()->OnError(this, msg);
    return;
  }

  std::string key;
  if (!EmbeddedURLToKey(url_, &key)) {
    std::string msg(
        base::StringPrintf("Invalid embedded URL: %s.", url_.spec().c_str()));
    handler()->OnError(this, msg);
    return;
  }

  GetEmbeddedData(key, options.start_offset, options.bytes_to_read);
}

void EmbeddedFetcher::GetEmbeddedData(const std::string& key,
                                      int64 start_offset, int64 bytes_to_read) {
  const char kDataNotFoundError[] = "Embedded data not found.";

  GeneratedResourceMap resource_map;
  LoaderEmbeddedResources::GenerateMap(resource_map);

  if (resource_map.find(key) == resource_map.end()) {
    handler()->OnError(this, kDataNotFoundError);
    return;
  }

  FileContents file_contents = resource_map[key];
  const char* data = reinterpret_cast<const char*>(file_contents.data);
  size_t size = static_cast<size_t>(file_contents.size);
  data += start_offset;
  size = std::min(size, static_cast<size_t>(bytes_to_read));

  handler()->OnReceived(this, data, size);
  handler()->OnDone(this);
}

bool EmbeddedFetcher::IsAllowedByCsp() {
  bool did_redirect = false;
  if (security_callback_.is_null() ||
      security_callback_.Run(url_, did_redirect)) {
    return true;
  } else {
    return false;
  }
}

}  // namespace loader
}  // namespace cobalt
