// Copyright 2018 The Fuchsia 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 "peridot/bin/suggestion_engine/query_runner.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/zx/time.h>

namespace modular {

namespace {

// Force queries to complete after some delay for better UX until/unless we can
// bring back staggered results in a way that isn't jarring and doesn't overly
// complicate the API.
constexpr zx::duration kQueryTimeout = zx::sec(9);

}  // namespace

class QueryRunner::HandlerRequest {
 public:
  HandlerRequest(fxl::WeakPtr<QueryRunner> runner,
                 const std::string& handler_url)
      : runner_(runner), handler_url_(handler_url) {}

  ~HandlerRequest() {
    if (!runner_)
      return;

    if (completed_) {
      FXL_VLOG(1) << "Handler " << handler_url_ << " complete";
    } else {
      FXL_LOG(WARNING) << "Handler " << handler_url_
                       << " closed without completing for query \""
                       << runner_->input_.text << "\".";
    }

    // find + erase rather than erase key to properly handle duplicate URLs
    // (only remove one)
    runner_->outstanding_handlers_.erase(
        runner_->outstanding_handlers_.find(handler_url_));
    FXL_VLOG(1) << runner_->outstanding_handlers_.size() << " remaining";
    if (runner_->outstanding_handlers_.empty()) {
      runner_->EndRequest();
    }
  }

  void Complete(fuchsia::modular::QueryResponse response) {
    if (runner_) {
      runner_->on_query_response_callback_(handler_url_, std::move(response));
      completed_ = true;
    }
  }

 private:
  fxl::WeakPtr<QueryRunner> runner_;
  std::string handler_url_;
  bool completed_ = false;

  FXL_DISALLOW_COPY_AND_ASSIGN(HandlerRequest);
};

QueryRunner::QueryRunner(
    fidl::InterfaceHandle<fuchsia::modular::QueryListener> listener,
    fuchsia::modular::UserInput input, int count)
    : listener_(listener.Bind()),
      input_(input),
      max_results_(count),
      request_ended_(false),
      weak_ptr_factory_(this) {}

// TODO(rosswang): Consider moving some of the cleanup logic into here, but
// beware that this may not happen until after the next QueryProcessor has been
// constructed (active_query_ = std::make_unique...).
QueryRunner::~QueryRunner() {
  if (!request_ended_) {
    EndRequest();
  }
}

void QueryRunner::Run(const std::vector<QueryHandlerRecord>& query_handlers) {
  if (query_handlers.empty()) {
    EndRequest();
  } else {
    for (const auto& handler_record : query_handlers) {
      DispatchQuery(handler_record);
    }

    async::PostDelayedTask(
        async_get_default_dispatcher(),
        [w = weak_ptr_factory_.GetWeakPtr()] {
          if (w) {
            w->TimeOut();
          }
        },
        kQueryTimeout);
  }
}

void QueryRunner::SetEndRequestCallback(fit::function<void()> callback) {
  on_end_request_callback_ = std::move(callback);
}

void QueryRunner::SetResponseCallback(
    fit::function<void(std::string, fuchsia::modular::QueryResponse)>
        callback) {
  on_query_response_callback_ = std::move(callback);
}

void QueryRunner::DispatchQuery(const QueryHandlerRecord& handler_record) {
  FXL_DCHECK(!request_ended_);

  outstanding_handlers_.insert(handler_record.url);

  handler_record.handler->OnQuery(
      input_, [request = std::make_shared<HandlerRequest>(
                   weak_ptr_factory_.GetWeakPtr(), handler_record.url)](
                  fuchsia::modular::QueryResponse response) {
        request->Complete(std::move(response));
      });
}

void QueryRunner::EndRequest() {
  FXL_DCHECK(!request_ended_);
  listener_->OnQueryComplete();
  on_end_request_callback_();
  weak_ptr_factory_.InvalidateWeakPtrs();
  request_ended_ = true;
}

void QueryRunner::TimeOut() {
  if (!outstanding_handlers_.empty()) {
    FXL_LOG(WARNING) << "Query timeout for \"" << input_.text
                     << "\". Still awaiting results from:";
    for (const std::string& handler_url : outstanding_handlers_) {
      FXL_LOG(WARNING) << "    " << handler_url;
    }
    EndRequest();
  }
}

}  // namespace modular
