/*
 * Copyright 2010 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: jmarantz@google.com (Joshua Marantz)

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

#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "pagespeed/kernel/base/charset_util.h"
#include "pagespeed/kernel/base/string_util.h"
#include "util/utf8/public/unicodetext.h"
#include "webutil/css/parser.h"

namespace net_instaweb {

class RewriteContext;

RewriteFilter::~RewriteFilter() {
}

void RewriteFilter::DetermineEnabled(GoogleString* disabled_reason) {
  set_is_enabled(true);
  if (UsesPropertyCacheDomCohort()) {
    driver()->set_write_property_cache_dom_cohort(true);
  }
}

const UrlSegmentEncoder* RewriteFilter::encoder() const {
  return driver()->default_encoder();
}

bool RewriteFilter::ComputeOnTheFly() const {
  return false;
}

RewriteContext* RewriteFilter::MakeRewriteContext() {
  return NULL;
}

RewriteContext* RewriteFilter::MakeNestedRewriteContext(
    RewriteContext* parent, const ResourceSlotPtr& slot) {
  return NULL;
}

StringPiece RewriteFilter::GetCharsetForScript(
    const Resource* script,
    const StringPiece attribute_charset,
    const StringPiece enclosing_charset) {
  // 1. If the script has a Content-Type with a charset, use that.
  if (!script->charset().empty()) {
    return script->charset();
  }

  // 2. If the element has a charset attribute, use that.
  if (!attribute_charset.empty()) {
    return attribute_charset;
  }

  // 3. If the script has a BOM, use that.
  StringPiece bom_charset =
      GetCharsetForBom(script->ExtractUncompressedContents());
  if (!bom_charset.empty()) {
    return bom_charset;
  }

  // 4. Use the charset of the enclosing page, if any.
  if (!enclosing_charset.empty()) {
    return enclosing_charset;
  }

  // Well, we really have no idea.
  return StringPiece();
}

GoogleString RewriteFilter::GetCharsetForStylesheet(
    const Resource* stylesheet,
    const StringPiece attribute_charset,
    const StringPiece enclosing_charset) {
  // 1. If the stylesheet has a Content-Type with a charset, use that, else
  if (!stylesheet->charset().empty()) {
    return stylesheet->charset().as_string();
  }

  // 2. If the stylesheet has an initial @charset, use that.
  StringPiece css(stylesheet->ExtractUncompressedContents());
  StripUtf8Bom(&css);
  Css::Parser parser(css);
  UnicodeText css_charset = parser.ExtractCharset();
  if (parser.errors_seen_mask() == 0) {
    GoogleString at_charset = UnicodeTextToUTF8(css_charset);
    if (!at_charset.empty()) {
      return at_charset;
    }
  }

  // 3. If the stylesheet has a BOM, use that.
  StringPiece bom_charset =
      GetCharsetForBom(stylesheet->ExtractUncompressedContents());
  if (!bom_charset.empty()) {
    return bom_charset.as_string();
  }

  // 4. If the element has a charset attribute, use that.
  if (!attribute_charset.empty()) {
    return attribute_charset.as_string();
  }

  // 5. Use the charset of the enclosing page, if any.
  if (!enclosing_charset.empty()) {
    return enclosing_charset.as_string();
  }

  // Well, we really have no idea.
  return GoogleString();
}

const RewriteOptions::Filter* RewriteFilter::RelatedFilters(
    int* num_filters) const {
  *num_filters = 0;
  return NULL;
}

}  // namespace net_instaweb
