/*
 * 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: sligocki@google.com (Shawn Ligocki)

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

#include "base/logging.h"
#include "net/instaweb/rewriter/public/output_resource.h"
#include "net/instaweb/rewriter/public/output_resource_kind.h"
#include "net/instaweb/rewriter/public/resource.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 "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/string_writer.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/content_type.h"

namespace net_instaweb {

class MessageHandler;

const char kStylesheet[] = "stylesheet";

const char CssOutlineFilter::kFilterId[] = "co";

CssOutlineFilter::CssOutlineFilter(RewriteDriver* driver)
    : CommonFilter(driver),
      inline_element_(NULL),
      inline_chars_(NULL),
      size_threshold_bytes_(driver->options()->css_outline_min_bytes()) {
}

CssOutlineFilter::~CssOutlineFilter() {}

void CssOutlineFilter::StartDocumentImpl() {
  inline_element_ = NULL;
  inline_chars_ = NULL;
}

void CssOutlineFilter::StartElementImpl(HtmlElement* element) {
  // No tags allowed inside style element.
  if (inline_element_ != NULL) {
    // TODO(sligocki): Add negative unit tests to hit these errors.
    driver()->ErrorHere("Tag '%s' found inside style.",
                        CEscape(element->name_str()).c_str());
    inline_element_ = NULL;  // Don't outline what we don't understand.
    inline_chars_ = NULL;
  }
  if (element->keyword() == HtmlName::kStyle &&
      element->FindAttribute(HtmlName::kScoped) == NULL) {
    // <style scoped> can't be directly converted to a <link>. We could
    // theoretically convert it to a <style scoped>@import ... </style>, but
    // given the feature has very little browser support, it's probably not
    // worth the effort, so we just leave it alone.
    // All other <style> blocks are candidates for conversion.
    inline_element_ = element;
    inline_chars_ = NULL;
  }
}

void CssOutlineFilter::EndElementImpl(HtmlElement* element) {
  if (inline_element_ != NULL) {
    CHECK(element == inline_element_);
    if (inline_chars_ != NULL &&
        inline_chars_->contents().size() >= size_threshold_bytes_) {
      OutlineStyle(inline_element_, inline_chars_->contents());
    }
    inline_element_ = NULL;
    inline_chars_ = NULL;
  }
}

void CssOutlineFilter::Flush() {
  // If we were flushed in a style element, we cannot outline it.
  inline_element_ = NULL;
  inline_chars_ = NULL;
}

void CssOutlineFilter::Characters(HtmlCharactersNode* characters) {
  if (inline_element_ != NULL) {
    CHECK(inline_chars_ == NULL) << "Multiple character blocks in style.";
    inline_chars_ = characters;
  }
}

// Try to write content and possibly header to resource.
bool CssOutlineFilter::WriteResource(const StringPiece& content,
                                     OutputResource* resource,
                                     MessageHandler* handler) {
  // We don't provide charset here since in general we can just inherit
  // from the page.
  // TODO(morlovich) check for proper behavior in case of embedded BOM.
  // TODO(matterbury) but AFAICT you cannot have a BOM in a <style> tag.
  return driver()->Write(
      ResourceVector(), content, &kContentTypeCss, StringPiece(), resource);
}

// Create file with style content and remove that element from DOM.
void CssOutlineFilter::OutlineStyle(HtmlElement* style_element,
                                    const GoogleString& content_str) {
  StringPiece content(content_str);
  if (driver()->IsRewritable(style_element)) {
    // Create style file from content.
    const char* type = style_element->AttributeValue(HtmlName::kType);
    // We only deal with CSS styles.  If no type specified, CSS is assumed.
    // See http://www.w3.org/TR/html5/semantics.html#the-style-element
    if (type == NULL || strcmp(type, kContentTypeCss.mime_type()) == 0) {
      MessageHandler* handler = driver()->message_handler();
      // Create outline resource at the document location,
      // not base URL location.
      GoogleString failure_reason;
      OutputResourcePtr output_resource(
          driver()->CreateOutputResourceWithUnmappedUrl(
              driver()->google_url(), kFilterId, "_", kOutlinedResource,
              &failure_reason));

      if (output_resource.get() == NULL) {
        driver()->InsertDebugComment(failure_reason, style_element);
      } else {
        // Rewrite URLs in content.
        GoogleString transformed_content;
        StringWriter writer(&transformed_content);
        bool content_valid = true;
        switch (driver()->ResolveCssUrls(base_url(),
                                         output_resource->resolved_base(),
                                         content,
                                         &writer, handler)) {
          case RewriteDriver::kNoResolutionNeeded:
            break;
          case RewriteDriver::kWriteFailed:
            content_valid = false;
            break;
          case RewriteDriver::kSuccess:
            content = transformed_content;
            break;
        }
        if (content_valid &&
            WriteResource(content, output_resource.get(), handler)) {
          HtmlElement* link_element = driver()->NewElement(
              style_element->parent(), HtmlName::kLink);
          driver()->AddAttribute(link_element, HtmlName::kRel, kStylesheet);
          driver()->AddAttribute(
              link_element, HtmlName::kHref, output_resource->url());
          // Add all style attributes to link.
          const HtmlElement::AttributeList& attrs = style_element->attributes();
          for (HtmlElement::AttributeConstIterator i(attrs.begin());
               i != attrs.end(); ++i) {
            const HtmlElement::Attribute& attr = *i;
            link_element->AddAttribute(attr);
          }
          // Add link to DOM.
          driver()->InsertNodeAfterNode(style_element, link_element);
          // Remove style element from DOM.
          if (!driver()->DeleteNode(style_element)) {
            driver()->FatalErrorHere("Failed to delete inline style element");
          }
        }
      }
    } else {
      driver()->InsertDebugComment(StrCat(
          "Cannot outline stylesheet with non-CSS type=", type), style_element);
      GoogleString element_string = style_element->ToString();
      driver()->InfoHere("Cannot outline non-css stylesheet %s",
                         element_string.c_str());
    }
  }
}

}  // namespace net_instaweb
