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

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

#include "base/logging.h"
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/output_resource.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 "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/google_url.h"

namespace net_instaweb {

SingleRewriteContext::SingleRewriteContext(RewriteDriver* driver,
                                           RewriteContext* parent,
                                           ResourceContext* resource_context)
    : RewriteContext(driver, parent, resource_context) {
}

SingleRewriteContext::~SingleRewriteContext() {
}

bool SingleRewriteContext::Partition(OutputPartitions* partitions,
                                     OutputResourceVector* outputs) {
  bool ret = false;
  if (num_slots() == 1) {
    ret = true;
    ResourcePtr resource(slot(0)->resource());
    GoogleString unsafe_reason;
    if (resource->IsSafeToRewrite(rewrite_uncacheable(), &unsafe_reason)) {
      GoogleString failure_reason;
      OutputResourcePtr output_resource(
          Driver()->CreateOutputResourceFromResource(
              id(), encoder(), resource_context(),
              resource, kind(), &failure_reason));
      if (output_resource.get() == NULL) {
        partitions->add_debug_message(failure_reason);
      } else {
        CachedResult* partition = partitions->add_partition();
        resource->AddInputInfoToPartition(Resource::kIncludeInputHash, 0,
                                          partition);
        output_resource->set_cached_result(partition);
        outputs->push_back(output_resource);
      }
    } else {
      partitions->add_debug_message(unsafe_reason);
    }
  }
  return ret;
}

void SingleRewriteContext::Rewrite(int partition_index,
                                   CachedResult* partition,
                                   const OutputResourcePtr& output_resource) {
  CHECK_EQ(0, partition_index);
  ResourcePtr resource(slot(0)->resource());
  CHECK(resource.get() != NULL);
  CHECK(resource->loaded());
  CHECK(resource->HttpStatusOk());
  if (output_resource.get() != NULL) {
    DCHECK_EQ(output_resource->cached_result(), partition);
  }
  RewriteSingle(resource, output_resource);
}

void SingleRewriteContext::AddLinkRelCanonical(
    const ResourcePtr& input, const OutputResourcePtr& output) {
  // It's unclear what we should do in case of complex domain mapping
  // configurations, so we simply avoid adding a header in that case.
  //
  // Also note that we may see both the original and rewritten URLs,
  // depending on whether we're handling the HTML or the resource fetch.
  const DomainLawyer* domain_lawyer = Options()->domain_lawyer();
  GoogleUrl input_gurl(input->url());
  if (domain_lawyer->WillDomainChange(input_gurl)) {
    return;
  }

  ConstStringStarVector rewritten_to;
  domain_lawyer->FindDomainsRewrittenTo(input_gurl, &rewritten_to);
  if (!rewritten_to.empty()) {
    return;
  }

  output->response_headers()->Add(
      HttpAttributes::kLink, RelCanonicalHeaderValue(input->url()));
}

GoogleString SingleRewriteContext::RelCanonicalHeaderValue(StringPiece url) {
  return StrCat("<", GoogleUrl::Sanitize(url), ">; rel=\"canonical\"");
}

}  // namespace net_instaweb
