// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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.

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

#include "net/instaweb/http/public/log_record.h"
#include "net/instaweb/rewriter/public/device_properties.h"
#include "net/instaweb/rewriter/public/downstream_caching_directives.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/user_agent_matcher.h"

namespace net_instaweb {

RequestProperties::RequestProperties(UserAgentMatcher* matcher)
    : device_properties_(new DeviceProperties(matcher)),
      downstream_caching_directives_(new DownstreamCachingDirectives()),
      supports_image_inlining_(kNotSet),
      supports_js_defer_(kNotSet),
      supports_lazyload_images_(kNotSet),
      supports_webp_in_place_(kNotSet),
      supports_webp_rewritten_urls_(kNotSet),
      supports_webp_lossless_alpha_(kNotSet),
      supports_webp_animated_(kNotSet) {
}

RequestProperties::~RequestProperties() {
}

void RequestProperties::SetUserAgent(StringPiece user_agent_string) {
  device_properties_->SetUserAgent(user_agent_string);
}

void RequestProperties::ParseRequestHeaders(
    const RequestHeaders& request_headers) {
  device_properties_->ParseRequestHeaders(request_headers);
  downstream_caching_directives_->ParseCapabilityListFromRequestHeaders(
                                      request_headers);
}


bool RequestProperties::SupportsImageInlining() const {
  if (supports_image_inlining_ == kNotSet) {
    supports_image_inlining_ =
        (downstream_caching_directives_->SupportsImageInlining() &&
         device_properties_->SupportsImageInlining()) ?
        kTrue :
        kFalse;
  }
  return (supports_image_inlining_ == kTrue);
}

bool RequestProperties::SupportsLazyloadImages() const {
  if (supports_lazyload_images_ == kNotSet) {
    supports_lazyload_images_ =
        (downstream_caching_directives_->SupportsLazyloadImages() &&
         device_properties_->SupportsLazyloadImages()) ?
        kTrue :
        kFalse;
  }
  return (supports_lazyload_images_ == kTrue);
}

bool RequestProperties::SupportsCriticalCss() const {
  return device_properties_->SupportsCriticalCss();
}

bool RequestProperties::AcceptsGzip() const {
  return device_properties_->AcceptsGzip();
}

bool RequestProperties::SupportsCriticalCssBeacon() const {
  // For bots, we don't allow instrumentation, but we do allow bots to use
  // previous instrumentation results collected by non-bots to enable the
  // prioritize_critical_css rewriter.
  return SupportsCriticalCss() && !IsBot();
}

bool RequestProperties::SupportsCriticalImagesBeacon() const {
  // For now this script has the same user agent requirements as image inlining,
  // however that could change in the future if more advanced JS is used by the
  // beacon.
  return device_properties_->SupportsCriticalImagesBeacon();
}

// Note that the result of the function is cached as supports_js_defer_. This
// must be cleared before calling the function a second time with a different
// value for allow_mobile.
bool RequestProperties::SupportsJsDefer(bool allow_mobile) const {
  if (supports_js_defer_ == kNotSet) {
    supports_js_defer_ =
        (downstream_caching_directives_->SupportsJsDefer() &&
         device_properties_->SupportsJsDefer(allow_mobile)) ?
        kTrue :
        kFalse;
  }
  return (supports_js_defer_ == kTrue);
}

bool RequestProperties::SupportsWebpInPlace() const {
  if (supports_webp_in_place_ == kNotSet) {
    supports_webp_in_place_ =
        (downstream_caching_directives_->SupportsWebp() &&
         device_properties_->SupportsWebpInPlace()) ?
        kTrue :
        kFalse;
  }
  return (supports_webp_in_place_ == kTrue);
}

bool RequestProperties::SupportsWebpRewrittenUrls() const {
  if (supports_webp_rewritten_urls_ == kNotSet) {
    supports_webp_rewritten_urls_ =
        (downstream_caching_directives_->SupportsWebp() &&
         device_properties_->SupportsWebpRewrittenUrls()) ?
        kTrue :
        kFalse;
  }
  return (supports_webp_rewritten_urls_ == kTrue);
}

bool RequestProperties::SupportsWebpLosslessAlpha() const {
  if (supports_webp_lossless_alpha_ == kNotSet) {
    supports_webp_lossless_alpha_ =
        (downstream_caching_directives_->SupportsWebpLosslessAlpha() &&
         device_properties_->SupportsWebpLosslessAlpha()) ?
        kTrue :
        kFalse;
  }
  return (supports_webp_lossless_alpha_ == kTrue);
}

bool RequestProperties::SupportsWebpAnimated() const {
  if (supports_webp_animated_ == kNotSet) {
    supports_webp_animated_ =
        (downstream_caching_directives_->SupportsWebpAnimated() &&
         device_properties_->SupportsWebpAnimated()) ?
        kTrue :
        kFalse;
  }
  return (supports_webp_animated_ == kTrue);
}

bool RequestProperties::IsBot() const {
  return device_properties_->IsBot();
}

bool RequestProperties::IsMobile() const {
  return device_properties_->IsMobile();
}

bool RequestProperties::IsTablet() const {
  return device_properties_->IsTablet();
}

bool RequestProperties::SupportsSplitHtml(bool allow_mobile) const {
  return device_properties_->SupportsSplitHtml(allow_mobile);
}

bool RequestProperties::CanPreloadResources() const {
  // TODO(anupama): Why do we not use a lazybool for this?
  return device_properties_->CanPreloadResources();
}

UserAgentMatcher::DeviceType RequestProperties::GetDeviceType() const {
  return device_properties_->GetDeviceType();
}

void RequestProperties::LogDeviceInfo(
    AbstractLogRecord* log_record,
    bool enable_aggressive_rewriters_for_mobile) {
  log_record->LogDeviceInfo(
      GetDeviceType(),
      SupportsImageInlining(),
      SupportsLazyloadImages(),
      SupportsCriticalImagesBeacon(),
      SupportsJsDefer(enable_aggressive_rewriters_for_mobile),
      SupportsWebpInPlace(),
      SupportsWebpRewrittenUrls(),
      SupportsWebpLosslessAlpha(),
      IsBot(),
      SupportsSplitHtml(enable_aggressive_rewriters_for_mobile),
      CanPreloadResources());
}

bool RequestProperties::ForbidWebpInlining() const {
  return device_properties_->ForbidWebpInlining();
}

bool RequestProperties::RequestsSaveData() const {
  return device_properties_->RequestsSaveData();
}

bool RequestProperties::HasViaHeader() const {
  return device_properties_->HasViaHeader();
}

}  // namespace net_instaweb
