/*
 * Copyright 2015 Google Inc.
 *
 * 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.
 */

// Author: morlovich@google.com (Maksim Orlovich)

#include "net/instaweb/rewriter/public/render_blocking_html_computation.h"

#include "base/logging.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/thread/queued_worker_pool.h"

namespace net_instaweb {

class RenderBlockingHtmlComputation::ResourceCallback
    : public Resource::AsyncCallback {
 public:
  ResourceCallback(RewriteDriver* parent_driver,
                   const ResourcePtr& resource,
                   RenderBlockingHtmlComputation* computation)
        : AsyncCallback(resource), parent_driver_(parent_driver),
          computation_(computation) {}

  virtual void Done(bool lock_failure, bool resource_ok) {
    // Shouldn't be enforcing locks on this anyway.
    DCHECK(!lock_failure);
    if (!resource_ok) {
      computation_->ReportResult(false);
      delete this;
    } else {
      parent_driver_->rewrite_worker()->Add(
          MakeFunction(this, &ResourceCallback::ParseAndFilter));
    }
  }

  void ParseAndFilter() {
    bool ok = false;
    scoped_ptr<RewriteDriver> child_driver(
        parent_driver_->server_context()->NewUnmanagedRewriteDriver(
            NULL /* no pool */,
            parent_driver_->options()->Clone(),
            parent_driver_->request_context()));
    // Keep it alive beyond auto-cleanup so client's Done can get info out of
    // filters.
    child_driver->set_externally_managed(true);

    computation_->SetupFilters(child_driver.get());
    if (!child_driver->StartParse(resource()->url())) {
      LOG(DFATAL) << "Huh? StartParse doesn't like URL, but resource fetched:"
                  << resource()->url();
      child_driver->Cleanup();
    } else {
      child_driver->ParseText(resource()->ExtractUncompressedContents());
      child_driver->FinishParse();
      ok = true;
    }

    computation_->ReportResult(ok);
    delete this;
  }

 private:
  RewriteDriver* parent_driver_;
  RenderBlockingHtmlComputation* computation_;
};

RenderBlockingHtmlComputation::RenderBlockingHtmlComputation(
    RewriteDriver* parent_driver) : parent_driver_(parent_driver) {}

void RenderBlockingHtmlComputation::Compute(const GoogleString& url) {
  parent_driver_->IncrementRenderBlockingAsyncEventsCount();

  GoogleUrl gurl(url);
  if (!gurl.IsWebValid()) {
    ReportResult(false);
    return;
  }

  bool is_authorized = false;
  ResourcePtr resource(
      parent_driver_->CreateInputResource(gurl, &is_authorized));
  if (resource.get() == NULL) {
    ReportResult(false);
    return;
  }

  // Don't cancel us willy-nilly. (Cancellation due to e.g. shutdown
  // will just look like failures to us and will be passed on to our
  // client).
  resource->set_is_background_fetch(false);
  ResourceCallback* resource_callback =
      new ResourceCallback(parent_driver_, resource, this);
  resource->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                      parent_driver_->request_context(),
                      resource_callback);
}

RenderBlockingHtmlComputation::~RenderBlockingHtmlComputation() {}

void RenderBlockingHtmlComputation::ReportResult(bool success) {
  Done(success);
  parent_driver_->DecrementRenderBlockingAsyncEventsCount();
  delete this;
}

}  // namespace net_instaweb
