/*
 * 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: jmaessen@google.com (Jan-Willem Maessen)

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

#include <set>
#include <vector>

#include "net/instaweb/rewriter/public/critical_finder_support_util.h"
#include "net/instaweb/rewriter/public/critical_selector_finder.h"
#include "net/instaweb/rewriter/public/css_tag_scanner.h"
#include "net/instaweb/rewriter/public/css_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/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/html/html_element.h"
#include "pagespeed/kernel/html/html_name.h"
#include "pagespeed/kernel/http/google_url.h"
#include "webutil/css/media.h"
#include "webutil/css/parser.h"
#include "webutil/css/selector.h"

using Css::Selectors;
using Css::Stylesheet;
using Css::Ruleset;
using Css::Rulesets;

namespace net_instaweb {

const char CriticalCssBeaconFilter::kInitializePageSpeedJs[] =
    "var pagespeed = pagespeed || {};";

// Counters.
const char CriticalCssBeaconFilter::kCriticalCssBeaconAddedCount[] =
    "critical_css_beacon_filter_script_added_count";
const char CriticalCssBeaconFilter::kCriticalCssNoBeaconDueToMissingData[] =
    "critical_css_no_beacon_due_to_missing_data";
const char CriticalCssBeaconFilter::kCriticalCssSkippedDueToCharset[] =
    "critical_css_skipped_due_to_charset";

CriticalCssBeaconFilter::CriticalCssBeaconFilter(RewriteDriver* driver)
    : CssSummarizerBase(driver) {
  Statistics* stats = driver->server_context()->statistics();
  critical_css_beacon_added_count_ = stats->GetVariable(
      kCriticalCssBeaconAddedCount);
  critical_css_no_beacon_due_to_missing_data_ = stats->GetVariable(
      kCriticalCssNoBeaconDueToMissingData);
  critical_css_skipped_due_to_charset_ = stats->GetVariable(
      kCriticalCssSkippedDueToCharset);
}

CriticalCssBeaconFilter::~CriticalCssBeaconFilter() {}

void CriticalCssBeaconFilter::InitStats(Statistics* statistics) {
  statistics->AddVariable(kCriticalCssBeaconAddedCount);
  statistics->AddVariable(kCriticalCssNoBeaconDueToMissingData);
  statistics->AddVariable(kCriticalCssSkippedDueToCharset);
}

bool CriticalCssBeaconFilter::MustSummarize(HtmlElement* element) const {
  // Don't summarize alternate stylesheets, they are clearly non-critical.
  if (element->keyword() == HtmlName::kLink &&
      CssTagScanner::IsAlternateStylesheet(
          element->AttributeValue(HtmlName::kRel))) {
    return false;
  }

  // Don't summarize non-screen-affecting or <noscript> CSS at all; the time we
  // spend doing that is better devoted to summarizing CSS selectors we will
  // actually consider critical.
  return (noscript_element() == NULL) &&
      css_util::CanMediaAffectScreen(element->AttributeValue(HtmlName::kMedia));
}

void CriticalCssBeaconFilter::Summarize(Stylesheet* stylesheet,
                                        GoogleString* out) const {
  StringSet selectors;
  FindSelectorsFromStylesheet(*stylesheet, &selectors);
  // Serialize set into out.
  AppendJoinCollection(out, selectors, ",");
}

// Append the selector list initialization JavaScript to |script|.
// Right now the result looks like:
//   pagespeed.selectors=["selector 1","selector 2","selector 3"];
void CriticalCssBeaconFilter::AppendSelectorsInitJs(
    GoogleString* script, const StringSet& selectors) {
  StrAppend(script, "pagespeed.selectors=[");
  for (StringSet::const_iterator i = selectors.begin();
       i != selectors.end(); ++i) {
    if (i != selectors.begin()) {
      StrAppend(script, ",");
    }
    EscapeToJsStringLiteral(*i, true /* quote */, script);
  }
  StrAppend(script, "];");
}

// Append the beacon initialization JavaScript to |script|.
// Right now the result looks like:
//   pagespeed.criticalCssBeaconInit('beacon_url','page_url','options_hash',
//        pagespeed.selectors);
void CriticalCssBeaconFilter::AppendBeaconInitJs(
    const BeaconMetadata& metadata, GoogleString* script) {
  GoogleString beacon_url = driver()->IsHttps() ?
      driver()->options()->beacon_url().https :
      driver()->options()->beacon_url().http;
  GoogleString page_url;
  EscapeToJsStringLiteral(driver()->google_url().Spec(), false /* add_quotes */,
                          &page_url);
  Hasher* hasher = driver()->server_context()->hasher();
  GoogleString options_hash = hasher->Hash(driver()->options()->signature());
  StrAppend(script,
            "pagespeed.criticalCssBeaconInit('",
            beacon_url, "','", page_url, "','",
            options_hash, "','", metadata.nonce, "',pagespeed.selectors);");
}

void CriticalCssBeaconFilter::SummariesDone() {
  // We parse each summary back into component selectors from its
  // comma-separated string, using a StringSet to remove duplicates (they'll be
  // sorted, too, which makes this easier to test).  We re-serialize the set.
  StringSet selectors;
  for (int i = 0; i < NumStyles(); ++i) {
    const SummaryInfo& summary_info = GetSummaryForStyle(i);
    // The critical_selector_filter doesn't include <noscript>-specific CSS
    // in the critical CSS it computes; so there is no need to figure out
    // critical selectors for such CSS.
    if (summary_info.is_inside_noscript) {
      continue;
    }
    switch (summary_info.state) {
      case kSummaryStillPending:
        // Don't beacon if we're still waiting for critical selector data.
        return;
      case kSummaryOk: {
        // Include the selectors in the beacon
        StringPieceVector temp;
        SplitStringPieceToVector(summary_info.data, ",", &temp,
                                 true /* omit_empty_strings */);
        for (StringPieceVector::const_iterator i = temp.begin(),
                 end = temp.end();
             i != end; ++i) {
          selectors.insert(i->as_string());
        }
        break;
      }
      case kSummarySlotRemoved:
        // Another filter (likely combine CSS) has eliminated this CSS.
        continue;
      case kSummaryCssParseError:
      case kSummaryResourceCreationFailed:
      case kSummaryInputUnavailable:
        // The CSS couldn't be fetched or parsed in some fashion.  This will
        // be left in place by the rewriter, so we don't need to consider it for
        // beaconing either.  NOTE: this requires the rewriter to inject
        // critical CSS in situ so that we don't disrupt the cascade order
        // around the unparseable data.
        // TODO(jmaessen): Consider handling unparseable data within the CSS
        // parse tree, which would let us extract critical CSS selectors from
        // CSS with a mix of parseable and unparseable rules.
        continue;
    }
  }
  BeaconMetadata metadata =
      driver()->server_context()->critical_selector_finder()->
          PrepareForBeaconInsertion(selectors, driver());
  if (metadata.status == kDoNotBeacon) {
    // No beaconing required according to current pcache state and computed
    // selector set.
    return;
  }

  // Insert the beaconing code and selectors.
  GoogleString script;
  StaticAssetManager* asset_manager =
      driver()->server_context()->static_asset_manager();
  if (driver()->server_context()->factory()->UseBeaconResultsInFilters()) {
    script = asset_manager->GetAsset(
        StaticAssetEnum::CRITICAL_CSS_BEACON_JS, driver()->options());
    AppendSelectorsInitJs(&script, selectors);
    AppendBeaconInitJs(metadata, &script);
  } else {
    script = kInitializePageSpeedJs;
    AppendSelectorsInitJs(&script, selectors);
  }
  HtmlElement* script_element = driver()->NewElement(NULL, HtmlName::kScript);
  driver()->AddAttribute(script_element, HtmlName::kDataPagespeedNoDefer, NULL);
  InsertNodeAtBodyEnd(script_element);
  AddJsToElement(script, script_element);

  if (critical_css_beacon_added_count_ != NULL) {
    critical_css_beacon_added_count_->Add(1);
  }
}

void CriticalCssBeaconFilter::DetermineEnabled(GoogleString* disabled_reason) {
  set_is_enabled(driver()->request_properties()->SupportsCriticalCssBeacon());
}

void CriticalCssBeaconFilter::FindSelectorsFromRuleset(
    const Ruleset& ruleset, StringSet* selectors) {
  const Selectors& rule_selectors = ruleset.selectors();
  for (int i = 0, n = rule_selectors.size(); i < n; ++i) {
    GoogleString trimmed(css_util::JsDetectableSelector(*rule_selectors[i]));
    if (!trimmed.empty()) {
      // Non-empty trimmed selector.  An empty trimmed selector (eg :hover,
      // which gets stripped away as it's not JS detectable) is *automatically*
      // critical, and we could also ignore the selector * (:hover is implicitly
      // *:hover).
      selectors->insert(trimmed);
    }
  }
}

// Returns false on parse failure, else records css selectors (in normalized
// string form) in selectors.  The selectors will be sorted and unique.  Logging
// of failures etc. should be done in the caller.
void CriticalCssBeaconFilter::FindSelectorsFromStylesheet(
    const Stylesheet& css, StringSet* selectors) {
  const Rulesets& rulesets = css.rulesets();
  for (int i = 0, n = rulesets.size(); i < n; ++i) {
    Ruleset* ruleset = rulesets[i];
    if (ruleset->type() == Ruleset::UNPARSED_REGION) {
      // Couldn't parse this as a rule.
      continue;
    }
    // Skip rules that can't apply to the screen.
    if (!css_util::CanMediaAffectScreen(ruleset->media_queries().ToString())) {
      continue;
    }
    // Record the selectors associated with this ruleset.
    FindSelectorsFromRuleset(*ruleset, selectors);
  }
}

}  // namespace net_instaweb
