/*
 * 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: morlovich@google.com (Maksim Orlovich)

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

#include "base/logging.h"
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/common_filter.h"
#include "net/instaweb/rewriter/public/output_resource_kind.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/resource_slot.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_result.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/html/html_element.h"

namespace net_instaweb {

InlineRewriteContext::InlineRewriteContext(CommonFilter* filter,
                                           HtmlElement* element,
                                           HtmlElement::Attribute* src)
    : RewriteContext(filter->driver(), NULL, NULL),
      filter_(filter),
      element_(element),
      src_(src) {
}

InlineRewriteContext::~InlineRewriteContext() {
}

bool InlineRewriteContext::StartInlining() {
  RewriteDriver* driver = filter_->driver();
  ResourcePtr input_resource;
  const char* url = src_->DecodedValueOrNull();
  if (url != NULL) {
    bool is_authorized;
    input_resource.reset(CreateResource(url, &is_authorized));
    if (input_resource.get() != NULL) {
      ResourceSlotPtr slot(driver->GetSlot(input_resource, element_, src_));
      AddSlot(slot);
      driver->InitiateRewrite(this);
      return true;
    }
    if (!is_authorized) {
      driver->InsertUnauthorizedDomainDebugComment(url, element_);
    }
  } else if (driver->DebugMode()) {
    driver->InsertDebugComment("Following resource not rewritten because its "
                               "src attribute cannot be decoded", element_);
  }
  delete this;
  return false;
}

ResourcePtr InlineRewriteContext::CreateResource(const char* url,
                                                 bool* is_authorized) {
  return filter_->CreateInputResource(url, is_authorized);
}

bool InlineRewriteContext::Partition(OutputPartitions* partitions,
                                     OutputResourceVector* outputs) {
  CHECK_EQ(1, num_slots()) << "InlineRewriteContext only handles one slot";
  ResourcePtr resource(slot(0)->resource());

  // Always create someplace to store stuff, since we may need debug info.
  CachedResult* partition = partitions->add_partition();
  outputs->push_back(OutputResourcePtr(NULL));

  bool ok = false;
  GoogleString reason_for_failure;
  if (!resource->IsSafeToRewrite(rewrite_uncacheable(), &reason_for_failure)) {
    AddRecheckDependency();
  } else {
    resource->AddInputInfoToPartition(Resource::kOmitInputHash, 0, partition);
    if (ShouldInline(resource, &reason_for_failure)) {
      StringPiece contents = resource->ExtractUncompressedContents();
      contents.CopyToString(partition->mutable_inlined_data());
      ok = true;
    }
  }

  if (!ok) {
    partition->add_debug_message(reason_for_failure);
  }

  return true;
}

void InlineRewriteContext::Rewrite(int partition_index,
                                   CachedResult* partition,
                                   const OutputResourcePtr& output_resource) {
  CHECK(output_resource.get() == NULL);
  CHECK_EQ(0, partition_index);

  // Mark slot as needing no further processing. Note that needs to be done
  // before calling RewriteDone, as that may cause us to be deleted!
  if (output_partition(0)->has_inlined_data()) {
    slot(0)->set_disable_further_processing(true);
  }

  // We signal as rewrite failed, as we do not create an output resource.
  RewriteDone(kRewriteFailed, 0);
}

void InlineRewriteContext::Render() {
  if (num_output_partitions() == 1 &&
      output_partition(0)->has_inlined_data() &&
      !slot(0)->should_delete_element()) {
    // We've decided to inline, and no one destroyed our element before us.
    // Set disable_rendering = true because we will render directly here.
    slot(0)->set_disable_rendering(true);
    ResourceSlotPtr our_slot = slot(0);
    RenderInline(
        our_slot->resource(), output_partition(0)->inlined_data(), element_);
  }
}

// We never create output resources, so methods related to them are stubbed.
OutputResourceKind InlineRewriteContext::kind() const {
  LOG(FATAL);
  return kRewrittenResource;
}

}  // namespace net_instaweb
