// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/workers/WorkletModuleResponsesMap.h"

#include "core/loader/modulescript/DocumentModuleScriptFetcher.h"
#include "platform/wtf/Optional.h"

namespace blink {

namespace {

bool IsValidURL(const KURL& url) {
  return !url.IsEmpty() && url.IsValid();
}

}  // namespace

class WorkletModuleResponsesMap::Entry final
    : public GarbageCollectedFinalized<Entry>,
      public ModuleScriptFetcher::Client {
  USING_GARBAGE_COLLECTED_MIXIN(WorkletModuleResponsesMap::Entry);

 public:
  enum class State { kInitial, kFetching, kFetched, kFailed };

  Entry() = default;
  ~Entry() = default;

  void Fetch(FetchParameters& fetch_params, ResourceFetcher* fetcher) {
    AdvanceState(State::kFetching);
    module_fetcher_ = new DocumentModuleScriptFetcher(fetcher);
    module_fetcher_->Fetch(fetch_params, this);
  }

  State GetState() const { return state_; }
  const ModuleScriptCreationParams& GetParams() const { return *params_; }

  void AddClient(WorkerOrWorkletModuleFetchCoordinator::Client* client) {
    // Clients can be added only while a module script is being fetched.
    DCHECK(state_ == State::kInitial || state_ == State::kFetching);
    clients_.push_back(client);
  }

  // Implements ModuleScriptFetcher::Client.
  //
  // Implementation of the second half of the custom fetch defined in the
  // "fetch a worklet script" algorithm:
  // https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
  void NotifyFetchFinished(
      const WTF::Optional<ModuleScriptCreationParams>& params,
      const HeapVector<Member<ConsoleMessage>>& error_messages) override {
    // The entry can be disposed of during the resource fetch.
    if (state_ == State::kFailed)
      return;

    if (!params) {
      // TODO(nhiroki): Add |error_messages| to the context's message storage.
      NotifyFailure();
      return;
    }

    AdvanceState(State::kFetched);

    // Step 7: "Let response be the result of fetch when it asynchronously
    // completes."
    // Step 8: "Set the value of the entry in cache whose key is url to
    // response, and asynchronously complete this algorithm with response."
    params_.emplace(*params);
    for (WorkerOrWorkletModuleFetchCoordinator::Client* client : clients_)
      client->OnFetched(*params);
    clients_.clear();
    module_fetcher_.Clear();
  }

  void NotifyFailure() {
    AdvanceState(State::kFailed);
    for (WorkerOrWorkletModuleFetchCoordinator::Client* client : clients_)
      client->OnFailed();
    clients_.clear();
    module_fetcher_.Clear();
  }

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(module_fetcher_);
    visitor->Trace(clients_);
  }

 private:
  void AdvanceState(State new_state) {
    switch (state_) {
      case State::kInitial:
        DCHECK_EQ(new_state, State::kFetching);
        break;
      case State::kFetching:
        DCHECK(new_state == State::kFetched || new_state == State::kFailed);
        break;
      case State::kFetched:
      case State::kFailed:
        NOTREACHED();
        break;
    }
    state_ = new_state;
  }

  State state_ = State::kInitial;

  Member<DocumentModuleScriptFetcher> module_fetcher_;

  WTF::Optional<ModuleScriptCreationParams> params_;
  HeapVector<Member<WorkerOrWorkletModuleFetchCoordinator::Client>> clients_;
};

WorkletModuleResponsesMap::WorkletModuleResponsesMap(ResourceFetcher* fetcher)
    : fetcher_(fetcher) {}

// Implementation of the first half of the custom fetch defined in the
// "fetch a worklet script" algorithm:
// https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
//
// "To perform the fetch given request, perform the following steps:"
// Step 1: "Let cache be the moduleResponsesMap."
// Step 2: "Let url be request's url."
void WorkletModuleResponsesMap::Fetch(FetchParameters& fetch_params,
                                      Client* client) {
  DCHECK(IsMainThread());
  if (!is_available_ || !IsValidURL(fetch_params.Url())) {
    client->OnFailed();
    return;
  }

  auto it = entries_.find(fetch_params.Url());
  if (it != entries_.end()) {
    Entry* entry = it->value;
    switch (entry->GetState()) {
      case Entry::State::kInitial:
        NOTREACHED();
        return;
      case Entry::State::kFetching:
        // Step 3: "If cache contains an entry with key url whose value is
        // "fetching", wait until that entry's value changes, then proceed to
        // the next step."
        entry->AddClient(client);
        return;
      case Entry::State::kFetched:
        // Step 4: "If cache contains an entry with key url, asynchronously
        // complete this algorithm with that entry's value, and abort these
        // steps."
        client->OnFetched(entry->GetParams());
        return;
      case Entry::State::kFailed:
        // Module fetching failed before. Abort following steps.
        client->OnFailed();
        return;
    }
    NOTREACHED();
  }

  // Step 5: "Create an entry in cache with key url and value "fetching"."
  Entry* entry = new Entry;
  entry->AddClient(client);
  entries_.insert(fetch_params.Url(), entry);

  // Step 6: "Fetch request."
  // Running the callback with an empty params will make the fetcher to fallback
  // to regular module loading and Write() will be called once the fetch is
  // complete.
  entry->Fetch(fetch_params, fetcher_.Get());
}

void WorkletModuleResponsesMap::Invalidate(const KURL& url) {
  DCHECK(IsMainThread());
  DCHECK(IsValidURL(url));
  if (!is_available_)
    return;

  DCHECK(entries_.Contains(url));
  Entry* entry = entries_.find(url)->value;
  entry->NotifyFailure();
}

void WorkletModuleResponsesMap::Dispose() {
  is_available_ = false;
  for (auto it : entries_) {
    switch (it.value->GetState()) {
      case Entry::State::kInitial:
        NOTREACHED();
        break;
      case Entry::State::kFetching:
        it.value->NotifyFailure();
        break;
      case Entry::State::kFetched:
      case Entry::State::kFailed:
        break;
    }
  }
  entries_.clear();
}

void WorkletModuleResponsesMap::Trace(blink::Visitor* visitor) {
  visitor->Trace(fetcher_);
  visitor->Trace(entries_);
}

}  // namespace blink
