// Copyright 2016 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/loader/loader_factory.h"

#include <memory>

#include "base/threading/platform_thread.h"
#include "cobalt/loader/image/threaded_image_decoder_proxy.h"

namespace cobalt {
namespace loader {

LoaderFactory::LoaderFactory(const char* name, FetcherFactory* fetcher_factory,
                             render_tree::ResourceProvider* resource_provider,
                             const base::DebuggerHooks& debugger_hooks,
                             size_t encoded_image_cache_capacity,
                             base::ThreadPriority loader_thread_priority)
    : ScriptLoaderFactory(name, fetcher_factory, loader_thread_priority),
      debugger_hooks_(debugger_hooks),
      resource_provider_(resource_provider) {
  if (encoded_image_cache_capacity > 0) {
    fetcher_cache_.reset(new FetcherCache(name, encoded_image_cache_capacity));
  }
}

std::unique_ptr<Loader> LoaderFactory::CreateImageLoader(
    const GURL& url, const Origin& origin,
    const csp::SecurityCallback& url_security_callback,
    const image::ImageDecoder::ImageAvailableCallback& image_available_callback,
    const Loader::OnCompleteFunction& load_complete_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Loader::FetcherCreator fetcher_creator = MakeCachedFetcherCreator(
      url, url_security_callback, kNoCORSMode, origin, disk_cache::kImage);

  std::unique_ptr<Loader> loader(new Loader(
      fetcher_creator,
      base::Bind(&image::ThreadedImageDecoderProxy::Create, resource_provider_,
                 &debugger_hooks_, image_available_callback,
                 load_thread_.message_loop()),
      load_complete_callback,
      base::Bind(&LoaderFactory::OnLoaderDestroyed, base::Unretained(this)),
      is_suspended_));

  OnLoaderCreated(loader.get());
  return loader;
}

std::unique_ptr<Loader> LoaderFactory::CreateLinkLoader(
    const GURL& url, const Origin& origin,
    const csp::SecurityCallback& url_security_callback,
    const loader::RequestMode cors_mode, const disk_cache::ResourceType type,
    const TextDecoder::TextAvailableCallback& link_available_callback,
    const Loader::OnCompleteFunction& load_complete_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Loader::FetcherCreator fetcher_creator =
      MakeFetcherCreator(url, url_security_callback, cors_mode, origin, type);

  std::unique_ptr<Loader> loader(new Loader(
      fetcher_creator,
      base::Bind(&loader::TextDecoder::Create, link_available_callback,
                 loader::TextDecoder::ResponseStartedCallback()),
      load_complete_callback,
      base::Bind(&LoaderFactory::OnLoaderDestroyed, base::Unretained(this)),
      is_suspended_));

  OnLoaderCreated(loader.get());
  return loader;
}

// Creates a loader that fetches and decodes a Mesh.
std::unique_ptr<Loader> LoaderFactory::CreateMeshLoader(
    const GURL& url, const Origin& origin,
    const csp::SecurityCallback& url_security_callback,
    const mesh::MeshDecoder::MeshAvailableCallback& mesh_available_callback,
    const Loader::OnCompleteFunction& load_complete_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Loader::FetcherCreator fetcher_creator =
      MakeFetcherCreator(url, url_security_callback, kNoCORSMode, origin);

  std::unique_ptr<Loader> loader(new Loader(
      fetcher_creator,
      base::Bind(&mesh::MeshDecoder::Create, resource_provider_,
                 mesh_available_callback),
      load_complete_callback,
      base::Bind(&LoaderFactory::OnLoaderDestroyed, base::Unretained(this)),
      is_suspended_));

  OnLoaderCreated(loader.get());
  return loader;
}

std::unique_ptr<Loader> LoaderFactory::CreateTypefaceLoader(
    const GURL& url, const Origin& origin,
    const csp::SecurityCallback& url_security_callback,
    const font::TypefaceDecoder::TypefaceAvailableCallback&
        typeface_available_callback,
    const Loader::OnCompleteFunction& load_complete_callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Loader::FetcherCreator fetcher_creator = MakeFetcherCreator(
      url, url_security_callback, kCORSModeSameOriginCredentials, origin,
      disk_cache::kFont);

  std::unique_ptr<Loader> loader(new Loader(
      fetcher_creator,
      base::Bind(&font::TypefaceDecoder::Create, resource_provider_,
                 typeface_available_callback),
      load_complete_callback,
      base::Bind(&LoaderFactory::OnLoaderDestroyed, base::Unretained(this)),
      is_suspended_));

  OnLoaderCreated(loader.get());
  return loader;
}

Loader::FetcherCreator LoaderFactory::MakeCachedFetcherCreator(
    const GURL& url, const csp::SecurityCallback& url_security_callback,
    RequestMode request_mode, const Origin& origin,
    const disk_cache::ResourceType type) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  auto fetcher_creator = MakeFetcherCreator(url, url_security_callback,
                                            request_mode, origin, type);

  if (fetcher_cache_) {
    return fetcher_cache_->GetFetcherCreator(url, fetcher_creator);
  }
  return fetcher_creator;
}

void LoaderFactory::NotifyResourceRequested(const std::string& url) {
  if (fetcher_cache_) {
    fetcher_cache_->NotifyResourceRequested(url);
  }
}

void LoaderFactory::Suspend() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(resource_provider_);
  DCHECK(!is_suspended_);

  is_suspended_ = true;
  resource_provider_ = NULL;
  SuspendActiveLoaders();
}

void LoaderFactory::Resume(render_tree::ResourceProvider* resource_provider) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(resource_provider);
  DCHECK(is_suspended_);

  is_suspended_ = false;
  ResumeActiveLoaders(resource_provider);
}

void LoaderFactory::UpdateResourceProvider(
    render_tree::ResourceProvider* resource_provider) {
  DCHECK(resource_provider);
  SuspendActiveLoaders();
  ResumeActiveLoaders(resource_provider);
}

void LoaderFactory::SuspendActiveLoaders() {
  for (LoaderSet::const_iterator iter = active_loaders_.begin();
       iter != active_loaders_.end(); ++iter) {
    (*iter)->Suspend();
  }

  // Wait for all loader thread messages to be flushed before returning.
  load_thread_.message_loop()->task_runner()->WaitForFence();
}

void LoaderFactory::ResumeActiveLoaders(
    render_tree::ResourceProvider* resource_provider) {
  resource_provider_ = resource_provider;

  for (LoaderSet::const_iterator iter = active_loaders_.begin();
       iter != active_loaders_.end(); ++iter) {
    (*iter)->Resume(resource_provider);
  }

  // Wait for all loader thread messages to be flushed before returning.
  load_thread_.message_loop()->task_runner()->WaitForFence();
}

}  // namespace loader
}  // namespace cobalt
