/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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/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
