/*
 * 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 "pagespeed/apache/apache_server_context.h"

#include <memory>

// http_protocol.h includes httpd.h. We need to include httpd_includes.h, which
// works around a conflicting definition of OK in gRPC.
#include "http_protocol.h"  // NOLINT
#include "net/instaweb/rewriter/config/measurement_proxy_rewrite_options_manager.h"
#include "net/instaweb/rewriter/public/measurement_proxy_url_namer.h"
#include "pagespeed/apache/apache_config.h"
#include "pagespeed/apache/apache_httpd_includes.h"
#include "pagespeed/apache/apache_request_context.h"
#include "pagespeed/apache/apache_rewrite_driver_factory.h"
#include "pagespeed/automatic/proxy_fetch.h"
#include "pagespeed/automatic/proxy_interface.h"
#include "pagespeed/kernel/base/file_system.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/http/http_names.h"

namespace net_instaweb {

const char ApacheServerContext::kProxyInterfaceStatsPrefix[] =
    "proxy-all-mode-";

ApacheServerContext::ApacheServerContext(ApacheRewriteDriverFactory* factory,
                                         server_rec* server,
                                         const StringPiece& version)
    : SystemServerContext(factory, server->server_hostname, server->port),
      apache_factory_(factory),
      server_rec_(server),
      version_(version.data(), version.size()) {
  // We may need the message handler for error messages very early, before
  // we get to InitServerContext in ChildInit().
  set_message_handler(apache_factory_->message_handler());

  // Currently, mod_pagespeed always runs upstream of mod_headers when used as
  // an origin server.  Note that in a proxy application, this might not be the
  // case.  I'm not sure how we can detect this on a per-request basis so
  // that might require a small refactor.
  //
  // TODO(jmarantz): We'd like to change this for various reasons but are unsure
  // of the impact.
  set_response_headers_finalized(false);
}

ApacheServerContext::~ApacheServerContext() {}

void ApacheServerContext::InitStats(Statistics* statistics) {
  ProxyInterface::InitStats(kProxyInterfaceStatsPrefix, statistics);
  SystemServerContext::InitStats(statistics);
}

bool ApacheServerContext::InitPath(const GoogleString& path) {
  if (file_system()->IsDir(path.c_str(), message_handler()).is_true()) {
    return true;
  }
  bool ok = file_system()->RecursivelyMakeDir(path, message_handler());
  if (ok) {
    apache_factory_->AddCreatedDirectory(path);
  }
  return ok;
}

ApacheConfig* ApacheServerContext::global_config() {
  return ApacheConfig::DynamicCast(global_options());
}

const ApacheConfig* ApacheServerContext::global_config() const {
  return ApacheConfig::DynamicCast(global_options());
}

ApacheConfig* ApacheServerContext::SpdyConfigOverlay() {
  // While we no longer actually use the spdy config overlay, it's still
  // useful for backwards compatibility during parsing.
  if (spdy_config_overlay_.get() == nullptr) {
    spdy_config_overlay_ =
        std::make_unique<ApacheConfig>("spdy_overlay", thread_system());
    // We want to copy any implicit rewrite level from the parent,
    // so we don't end up overriding it with passthrough. It's also OK
    // to forward explicit one to an implicit one here, since an implicit
    // will never override an explicit one (even if its different).
    spdy_config_overlay_->SetDefaultRewriteLevel(global_config()->level());
  }
  return spdy_config_overlay_.get();
}

ApacheConfig* ApacheServerContext::NonSpdyConfigOverlay() {
  if (non_spdy_config_overlay_.get() == nullptr) {
    non_spdy_config_overlay_ =
        std::make_unique<ApacheConfig>("non_spdy_overlay", thread_system());
    // See ::SpdyConfigOverlay for explanation.
    non_spdy_config_overlay_->SetDefaultRewriteLevel(global_config()->level());
  }
  return non_spdy_config_overlay_.get();
}

void ApacheServerContext::CollapseConfigOverlaysAndComputeSignatures() {
  // These days we ignore the spdy overlay and merge-in the non-spdy one
  // unconditionally.
  if (non_spdy_config_overlay_.get() != nullptr) {
    global_config()->Merge(*non_spdy_config_overlay_);
  }

  SystemServerContext::CollapseConfigOverlaysAndComputeSignatures();

  spdy_config_overlay_.reset();
  non_spdy_config_overlay_.reset();
}

bool ApacheServerContext::PoolDestroyed() {
  DCHECK_EQ(num_active_rewrite_drivers(), 0);
  return apache_factory_->PoolDestroyed(this);
}

void ApacheServerContext::InitProxyFetchFactory() {
  proxy_fetch_factory_ = std::make_unique<ProxyFetchFactory>(this);
}

ApacheRequestContext* ApacheServerContext::NewApacheRequestContext(
    request_rec* request) {
  return new ApacheRequestContext(thread_system()->NewMutex(), timer(),
                                  request);
}

void ApacheServerContext::ReportNotFoundHelper(MessageType message_type,
                                               StringPiece error_message,
                                               request_rec* request,
                                               Variable* error_count) {
  error_count->Add(1);
  request->status = HttpStatus::kNotFound;
  ap_send_error_response(request, 0);
  message_handler()->Message(
      message_type, "%s %s: not found (404)",
      (error_message.empty() ? "(null)" : error_message.as_string().c_str()),
      error_count->GetName().as_string().c_str());
}

GoogleString ApacheServerContext::FormatOption(StringPiece option_name,
                                               StringPiece args) {
  return StrCat("ModPagespeed", option_name, " ", args);
}

void ApacheServerContext::ChildInit(SystemRewriteDriverFactory* f) {
  if (global_config()->proxy_all_requests_mode()) {
    apache_factory_->SetNeedSchedulerThread();
    if (global_config()->measurement_proxy_mode()) {
      measurement_url_namer_ = std::make_unique<MeasurementProxyUrlNamer>(
          global_config()->measurement_proxy_root(),
          global_config()->measurement_proxy_password());
      set_url_namer(measurement_url_namer_.get());
      SetRewriteOptionsManager(new MeasurementProxyRewriteOptionsManager(
          this, global_config()->measurement_proxy_root(),
          global_config()->measurement_proxy_password()));
    }
  }
  SystemServerContext::ChildInit(f);
}

}  // namespace net_instaweb
