/*
 * Copyright 2012 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: nikhilmadan@google.com (Nikhil Madan)

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

#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_query.h"
#include "pagespeed/kernel/base/escaping.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/html/html_element.h"
#include "pagespeed/kernel/html/html_name.h"
#include "pagespeed/kernel/html/html_node.h"
#include "pagespeed/kernel/http/google_url.h"

namespace {

const char kScript[] = "window.location=\"%s\";";

}  // namespace

namespace net_instaweb {

RedirectOnSizeLimitFilter::RedirectOnSizeLimitFilter(
    RewriteDriver* rewrite_driver)
    : CommonFilter(rewrite_driver),
      redirect_inserted_(false) {
}

RedirectOnSizeLimitFilter::~RedirectOnSizeLimitFilter() {
}

void RedirectOnSizeLimitFilter::StartDocumentImpl() {
  redirect_inserted_ = false;
}

void RedirectOnSizeLimitFilter::StartElementImpl(HtmlElement* element) {
  InsertScriptIfNeeded(element, true);
}


void RedirectOnSizeLimitFilter::EndElementImpl(HtmlElement* element) {
  InsertScriptIfNeeded(element, false);
}

void RedirectOnSizeLimitFilter::InsertScriptIfNeeded(HtmlElement* element,
                                                     bool is_start) {
  if (!redirect_inserted_ && noscript_element() == NULL &&
      driver()->size_limit_exceeded()) {
    scoped_ptr<GoogleUrl> url_with_psa_off(
        driver()->google_url().CopyAndAddQueryParam(
            RewriteQuery::kPageSpeed, "off"));
    GoogleString url_str;
    EscapeToJsStringLiteral(url_with_psa_off->Spec(), false, &url_str);

    HtmlElement* script = driver()->NewElement(
        element, HtmlName::kScript);
    driver()->AddAttribute(script, HtmlName::kType, "text/javascript");
    HtmlNode* script_code = driver()->NewCharactersNode(
      script, StringPrintf(kScript, url_str.c_str()));
    // For HTML elements, add the script as a child. Otherwise, insert the
    // script before or after the element.
    if (element->keyword() == HtmlName::kHtml) {
      if (is_start) {
        driver()->PrependChild(element, script);
      } else {
        driver()->AppendChild(element, script);
      }
    } else if (is_start) {
      driver()->InsertNodeBeforeNode(element, script);
    } else {
      driver()->InsertNodeAfterNode(element, script);
    }
    driver()->AppendChild(script, script_code);
    redirect_inserted_ = true;
  }
}

}  // namespace net_instaweb
