/*
 * Copyright 2011 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/lazyload_images_filter.h"

#include "base/logging.h"
#include "net/instaweb/http/public/log_record.h"
#include "net/instaweb/rewriter/public/critical_images_finder.h"
#include "net/instaweb/rewriter/public/request_properties.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 "net/instaweb/rewriter/public/static_asset_manager.h"
#include "net/instaweb/util/public/fallback_property_page.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/data_url.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/opt/logging/enums.pb.h"

namespace net_instaweb {

namespace {

const char kTrue[] = "true";
const char kFalse[] = "false";
const char kJquerySlider[] = "jquery.sexyslider";

}  // namespace

const char* LazyloadImagesFilter::kImageOnloadCode =
    "pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);";

const char* LazyloadImagesFilter::kLoadAllImages =
    "pagespeed.lazyLoadImages.loadAllImages();";

const char* LazyloadImagesFilter::kOverrideAttributeFunctions =
    "pagespeed.lazyLoadImages.overrideAttributeFunctions();";

const char* LazyloadImagesFilter::kIsLazyloadScriptInsertedPropertyName =
    "is_lazyload_script_inserted";

LazyloadImagesFilter::LazyloadImagesFilter(RewriteDriver* driver)
    : CommonFilter(driver) {
  Clear();
  blank_image_url_ = GetBlankImageSrc(
      driver->options(),
      driver->server_context()->static_asset_manager());
}
LazyloadImagesFilter::~LazyloadImagesFilter() {}

void LazyloadImagesFilter::DetermineEnabled(GoogleString* disabled_reason) {
  RewriterHtmlApplication::Status should_apply = ShouldApply(driver());
  set_is_enabled(should_apply == RewriterHtmlApplication::ACTIVE);
  if (!driver()->flushing_early()) {
    driver()->log_record()->LogRewriterHtmlStatus(
        RewriteOptions::FilterId(RewriteOptions::kLazyloadImages),
        should_apply);
  }
}

void LazyloadImagesFilter::StartDocumentImpl() {
  Clear();
}

void LazyloadImagesFilter::EndDocument() {
  // TODO(jmaessen): Fix filter to insert this script
  // conditionally.
  driver()->UpdatePropertyValueInDomCohort(
      driver()->fallback_property_page(),
      kIsLazyloadScriptInsertedPropertyName,
      main_script_inserted_ ? "1" : "0");
}

void LazyloadImagesFilter::Clear() {
  skip_rewrite_ = NULL;
  head_element_ = NULL;
  main_script_inserted_ = false;
  abort_rewrite_ = false;
  abort_script_inserted_ = false;
  num_images_lazily_loaded_ = 0;
}

RewriterHtmlApplication::Status LazyloadImagesFilter::ShouldApply(
    RewriteDriver* driver) {
  // Note: there's similar UA logic in
  // DedupInlinedImagedFilter::DetermineEnabled, so if this logic changes that
  // logic may well require alteration too.
  if (!driver->request_properties()->SupportsLazyloadImages()) {
    return RewriterHtmlApplication::USER_AGENT_NOT_SUPPORTED;
  }
  if (driver->flushing_early() ||
      (driver->request_headers() != NULL &&
       driver->request_headers()->IsXmlHttpRequest())) {
    return RewriterHtmlApplication::DISABLED;
  }
  CriticalImagesFinder* finder =
      driver->server_context()->critical_images_finder();
  if (finder->Available(driver) == CriticalImagesFinder::kNoDataYet) {
    // Don't lazyload images on a page that's waiting for critical image data.
    // However, this page should later be rewritten when data arrives.  Contrast
    // this with the case where beaconing is explicitly disabled, and all images
    // are lazy loaded.
    return RewriterHtmlApplication::DISABLED;
  }
  return RewriterHtmlApplication::ACTIVE;
}

void LazyloadImagesFilter::StartElementImpl(HtmlElement* element) {
  if (noscript_element() != NULL) {
    return;
  }
  if (!main_script_inserted_ && head_element_ == NULL) {
    switch (element->keyword()) {
      case HtmlName::kHtml:
      case HtmlName::kLink:
      case HtmlName::kMeta:
      case HtmlName::kScript:
      case HtmlName::kStyle:
        break;
      case HtmlName::kHead:
        head_element_ = element;
        break;
      default:
        InsertLazyloadJsCode(element);
        break;
    }
  }
  if (skip_rewrite_ == NULL) {
    if (element->keyword() == HtmlName::kNoembed ||
        element->keyword() == HtmlName::kMarquee) {
      skip_rewrite_ = element;
      return;
    }
    // Check if lazyloading is enabled for the given class name. If not,
    // skip rewriting all images till we reach the end of this element.
    HtmlElement::Attribute* class_attribute = element->FindAttribute(
        HtmlName::kClass);
    if (class_attribute != NULL) {
      StringPiece class_value(class_attribute->DecodedValueOrNull());
      if (!class_value.empty()) {
        GoogleString class_string;
        class_value.CopyToString(&class_string);
        LowerString(&class_string);
        if (!driver()->options()->IsLazyloadEnabledForClassName(
            class_string)) {
          skip_rewrite_ = element;
          return;
        }
      }
    }
  }
  if (element->keyword() == HtmlName::kScript) {
    // This filter does not currently work with the jquery slider. We just don't
    // rewrite the page in this case.
    HtmlElement::Attribute* src = element->FindAttribute(HtmlName::kSrc);
    if (src != NULL) {
      StringPiece url(src->DecodedValueOrNull());
      if (url.find(kJquerySlider) != StringPiece::npos) {
        abort_rewrite_ = true;
        return;
      }
    }
    InsertOverrideAttributesScript(element, true);
  }
}

void LazyloadImagesFilter::EndElementImpl(HtmlElement* element) {
  if (noscript_element() != NULL || skip_rewrite_ != NULL) {
    if (skip_rewrite_ == element) {
      skip_rewrite_ = NULL;
    }
    return;
  }
  if (head_element_ == element) {
    InsertLazyloadJsCode(NULL);
    head_element_ = NULL;
  }
  if (abort_rewrite_) {
    if (!abort_script_inserted_ && main_script_inserted_ &&
        num_images_lazily_loaded_ > 0) {
      // If we have already rewritten some elements on the page, insert a
      // script to load all previously rewritten images.
      HtmlElement* script = driver()->NewElement(element, HtmlName::kScript);
      driver()->AddAttribute(script, HtmlName::kType, "text/javascript");
      HtmlNode* script_code = driver()->NewCharactersNode(
          script, kLoadAllImages);
      driver()->InsertNodeAfterNode(element, script);
      driver()->AppendChild(script, script_code);
      abort_script_inserted_ = true;
    }
    return;
  }
  if (element->keyword() == HtmlName::kBody) {
    InsertOverrideAttributesScript(element, false);
    return;
  }
  // Only rewrite <img> tags. Don't rewrite <input> tags since the onload
  // event is not fired for them in some browsers.
  if (!driver()->IsRewritable(element) ||
      element->keyword() != HtmlName::kImg) {
    return;
  }

  HtmlElement::Attribute* src = element->FindAttribute(HtmlName::kSrc);
  if (src == NULL) {
    return;
  }

  StringPiece url(src->DecodedValueOrNull());
  if (url.empty() || IsDataUrl(url) ||
      element->FindAttribute(HtmlName::kDataPagespeedNoDefer) != NULL ||
      element->FindAttribute(HtmlName::kPagespeedNoDefer) != NULL) {
    // TODO(rahulbansal): Log separately for pagespeed_no_defer.
    return;
  }
  AbstractLogRecord* log_record = driver()->log_record();
  if (!CanAddPagespeedOnloadToImage(*element) ||
      element->FindAttribute(HtmlName::kDataPagespeedLazySrc) != NULL ||
      element->FindAttribute(HtmlName::kDataSrc) != NULL) {
    log_record->LogLazyloadFilter(
        RewriteOptions::FilterId(RewriteOptions::kLazyloadImages),
        RewriterApplication::NOT_APPLIED, false, false);
    return;
  }
  // Decode the url if it is rewritten.
  GoogleUrl gurl(base_url(), url);
  StringVector decoded_url_vector;
  if (driver()->DecodeUrl(gurl, &decoded_url_vector) &&
      decoded_url_vector.size() == 1) {
    // We only handle the case where the rewritten url corresponds to
    // a single original url which should be sufficient for all cases
    // other than image sprites.
    gurl.Reset(decoded_url_vector[0]);
  }
  if (!gurl.IsAnyValid()) {
    // Do not lazily load images with invalid urls.
    return;
  }
  StringPiece full_url = gurl.Spec();
  if (full_url.empty()) {
    return;
  }
  if (!driver()->options()->IsAllowed(full_url)) {
    // Do not lazily load images with blacklisted urls.
    log_record->LogLazyloadFilter(
        RewriteOptions::FilterId(RewriteOptions::kLazyloadImages),
        RewriterApplication::NOT_APPLIED, true, false);
    return;
  }

  CriticalImagesFinder* finder =
      driver()->server_context()->critical_images_finder();
  // Note that if the platform lacks a CriticalImageFinder implementation, we
  // consider all images to be non-critical and try to lazily load them.
  // Similarly, if we have disabled data gathering for lazy load, we again lazy
  // load all images.  If, however, we simply haven't gathered enough data yet,
  // we consider all images to be critical and disable lazy loading (in
  // ShouldApply above) in order to provide better above-the-fold loading.
  if (finder->Available(driver()) == CriticalImagesFinder::kAvailable) {
    // Decode the url since the critical images in the finder are not
    // rewritten.
    if (finder->IsHtmlCriticalImage(full_url, driver())) {
      log_record->LogLazyloadFilter(
          RewriteOptions::FilterId(RewriteOptions::kLazyloadImages),
          RewriterApplication::NOT_APPLIED, false, true);
      // Do not try to lazily load this image since it is critical.
      return;
    }
  }
  if (!main_script_inserted_) {
    InsertLazyloadJsCode(element);
  }
  // Replace the src with data-pagespeed-lazy-src.
  driver()->SetAttributeName(src, HtmlName::kDataPagespeedLazySrc);
  // Rename srcset -> data-pagespeed-high-res-srcset
  HtmlElement::Attribute* srcset =
      element->FindAttribute(HtmlName::kSrcset);
  if (srcset != NULL) {
    driver()->SetAttributeName(srcset, HtmlName::kDataPagespeedLazySrcset);
  }
  driver()->AddAttribute(element, HtmlName::kSrc, blank_image_url_);
  log_record->LogLazyloadFilter(
      RewriteOptions::FilterId(RewriteOptions::kLazyloadImages),
      RewriterApplication::APPLIED_OK, false, false);
  // Add an onload function to load the image if it is visible and then do
  // the criticality check. Since we check CanAddPagespeedOnloadToImage
  // before coming here, the only onload handler that we would delete would
  // be the one added by our very own beaconing code. We re-introduce this
  // beaconing onload logic via kImageOnloadCode.
  // TODO(jud): Add these with addEventListener rather than with the attributes.
  element->DeleteAttribute(HtmlName::kOnload);
  driver()->AddAttribute(element, HtmlName::kOnload, kImageOnloadCode);
  // Add onerror handler just in case the temporary pixel doesn't load.
  element->DeleteAttribute(HtmlName::kOnerror);
  // Note: this.onerror=null to avoid infinitely repeating on failure:
  //   See: http://stackoverflow.com/questions/3984287
  driver()->AddAttribute(element, HtmlName::kOnerror,
                         StrCat("this.onerror=null;", kImageOnloadCode));
  ++num_images_lazily_loaded_;
}

void LazyloadImagesFilter::InsertLazyloadJsCode(HtmlElement* element) {
  if (!driver()->is_lazyload_script_flushed() &&
      (!abort_rewrite_ || num_images_lazily_loaded_ > 0)) {
    HtmlElement* script = driver()->NewElement(element, HtmlName::kScript);
    if (element != NULL) {
      driver()->InsertNodeBeforeNode(element, script);
    } else if (driver()->CanAppendChild(head_element_)) {
      // insert at end of head.
      driver()->AppendChild(head_element_, script);
    } else {
      // Could not insert at end of head even though we just saw the end of head
      // event!  Should not happen, but this will ensure that we insert the
      // script before the next tag we see.
      LOG(DFATAL) << "Can't append child to <head> at the </head> event!";
      main_script_inserted_ = false;
      return;
    }
    StaticAssetManager* static_asset_manager =
        driver()->server_context()->static_asset_manager();
    GoogleString lazyload_js = GetLazyloadJsSnippet(
        driver()->options(), static_asset_manager);
    AddJsToElement(lazyload_js, script);
    driver()->AddAttribute(script, HtmlName::kDataPagespeedNoDefer, NULL);
  }
  main_script_inserted_ = true;
}

void LazyloadImagesFilter::InsertOverrideAttributesScript(
    HtmlElement* element, bool is_before_script) {
  if (num_images_lazily_loaded_ > 0) {
    HtmlElement* script = driver()->NewElement(element, HtmlName::kScript);
    driver()->AddAttribute(script, HtmlName::kType, "text/javascript");
    driver()->AddAttribute(script, HtmlName::kDataPagespeedNoDefer, NULL);
    HtmlNode* script_code = driver()->NewCharactersNode(
        script, kOverrideAttributeFunctions);
    if (is_before_script) {
      driver()->InsertNodeBeforeNode(element, script);
    } else {
      driver()->AppendChild(element, script);
    }
    driver()->AppendChild(script, script_code);
    num_images_lazily_loaded_ = 0;
  }
}

GoogleString LazyloadImagesFilter::GetBlankImageSrc(
    const RewriteOptions* options,
    const StaticAssetManager* static_asset_manager) {
  const GoogleString& options_url = options->lazyload_images_blank_url();
  if (options_url.empty()) {
    return static_asset_manager->GetAssetUrl(StaticAssetEnum::BLANK_GIF,
                                             options);
  } else {
    return options_url;
  }
}

GoogleString LazyloadImagesFilter::GetLazyloadJsSnippet(
    const RewriteOptions* options,
    StaticAssetManager* static_asset_manager) {
  const GoogleString& load_onload =
      options->lazyload_images_after_onload() ? kTrue : kFalse;
  StringPiece lazyload_images_js =
      static_asset_manager->GetAsset(
          StaticAssetEnum::LAZYLOAD_IMAGES_JS, options);
  const GoogleString& blank_image_url =
      GetBlankImageSrc(options, static_asset_manager);
  GoogleString lazyload_js =
      StrCat(lazyload_images_js, "\npagespeed.lazyLoadInit(",
             load_onload, ", \"", blank_image_url, "\");\n");
  return lazyload_js;
}

}  // namespace net_instaweb
