/*
 * Copyright 2013 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: jud@google.com (Jud Porter)

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

#include <algorithm>

#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/rewriter/critical_keys.pb.h"
#include "net/instaweb/rewriter/public/beacon_critical_line_info_finder.h"
#include "net/instaweb/rewriter/public/critical_finder_support_util.h"
#include "net/instaweb/rewriter/public/critical_line_info_finder.h"
#include "net/instaweb/rewriter/public/property_cache_util.h"
#include "net/instaweb/rewriter/public/request_properties.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/rewriter/public/static_asset_manager.h"
#include "pagespeed/kernel/base/escaping.h"
#include "pagespeed/kernel/base/hasher.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/html/html_element.h"
#include "pagespeed/kernel/html/html_name.h"
#include "pagespeed/kernel/http/google_url.h"

namespace net_instaweb {

// Counters.
const char SplitHtmlBeaconFilter::kSplitHtmlBeaconAddedCount[] =
    "split_html_beacon_filter_script_added_count";

SplitHtmlBeaconFilter::SplitHtmlBeaconFilter(RewriteDriver* driver)
    : CommonFilter(driver) {
  Statistics* stats = driver->server_context()->statistics();
  split_html_beacon_added_count_ =
      stats->GetVariable(kSplitHtmlBeaconAddedCount);
}

void SplitHtmlBeaconFilter::DetermineEnabled(GoogleString* disabled_reason) {
  set_is_enabled(ShouldApply(driver()));
}

void SplitHtmlBeaconFilter::InitStats(Statistics* statistics) {
  statistics->AddVariable(kSplitHtmlBeaconAddedCount);
}

bool SplitHtmlBeaconFilter::ShouldApply(RewriteDriver* driver) {
  if (driver->request_properties()->IsBot()) {
    return false;
  }
  // Do not instrument if the x_split query param was set to request either the
  // above or below the fold content.
  bool is_split_request = driver->request_context()->split_request_type() !=
                          RequestContext::SPLIT_FULL;
  if (is_split_request ||
      !driver->server_context()->factory()->UseBeaconResultsInFilters() ||
      !driver->options()->Enabled(RewriteOptions::kSplitHtml)) {
    return false;
  }

  const CriticalLineInfoFinder* finder =
      driver->server_context()->critical_line_info_finder();

  // Check if we have critical line info in the pcache, and only beacon if it
  // is missing or expired.
  // TODO(jud): We need a smarter reinstrumentation strategy here than just
  // waiting for the pcache to expire. To start, we need to collect an adequate
  // number of samples in the beginning until we reach a steady state, and then
  // back off our sampling rate. Then, we should detect when the page changes
  // substantially and increase beaconing rate again until we've collected
  // enough samples on the updated page. We also should detect the case where we
  // aren't receiving beacons correctly for whatever reason, and stop
  // instrumenting, since this beacon is more computationally expensive than say
  // the critical image beacon.
  int64 expiration_time_ms = std::min(
      driver->options()->finder_properties_cache_expiration_time_ms(),
      driver->options()->beacon_reinstrument_time_sec() * Timer::kSecondMs);
  PropertyCacheDecodeResult result;
  scoped_ptr<CriticalKeys> critical_keys(DecodeFromPropertyCache<CriticalKeys>(
      driver, finder->cohort(),
      BeaconCriticalLineInfoFinder::kBeaconCriticalLineInfoPropertyName,
      expiration_time_ms, &result));
  return result != kPropertyCacheDecodeOk;
}

void SplitHtmlBeaconFilter::EndDocument() {
  BeaconMetadata beacon_metadata = driver()->server_context()
                                       ->critical_line_info_finder()
                                       ->PrepareForBeaconInsertion(driver());
  if (beacon_metadata.status == kDoNotBeacon) {
    return;
  }
  StaticAssetManager* static_asset_manager =
      driver()->server_context()->static_asset_manager();
  GoogleString js = static_asset_manager->GetAsset(
      StaticAssetEnum::SPLIT_HTML_BEACON_JS, driver()->options());

  // Create the init string to append at the end of the static JS.
  const RewriteOptions::BeaconUrl& beacons = driver()->options()->beacon_url();
  const GoogleString* beacon_url =
      driver()->IsHttps() ? &beacons.https : &beacons.http;
  GoogleString html_url;
  EscapeToJsStringLiteral(driver()->google_url().Spec(), false, /* no quotes */
                          &html_url);
  GoogleString options_signature_hash = driver()->server_context()->hasher()
      ->Hash(driver()->options()->signature());

  StrAppend(&js, "\npagespeed.splitHtmlBeaconInit(");
  StrAppend(&js, "'", *beacon_url, "', ");
  StrAppend(&js, "'", html_url, "', ");
  StrAppend(&js, "'", options_signature_hash, "', ");
  StrAppend(&js, "'", beacon_metadata.nonce, "');");

  HtmlElement* script = driver()->NewElement(NULL, HtmlName::kScript);
  InsertNodeAtBodyEnd(script);
  AddJsToElement(js, script);
  driver()->AddAttribute(script, HtmlName::kDataPagespeedNoDefer, NULL);
  split_html_beacon_added_count_->Add(1);
}

}  // namespace net_instaweb
