/*
 * Copyright 2012 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: nforman@google.com (Naomi Forman)
//
// Functionality for manipulating exeriment state and cookies.

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

#include <cstdlib>

#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "pagespeed/kernel/base/time_util.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/http/user_agent_matcher.h"

namespace net_instaweb {
namespace experiment {

bool GetExperimentCookieState(const RequestHeaders& headers, int* value) {
  ConstStringStarVector v;
  *value = kExperimentNotSet;
  if (headers.Lookup(HttpAttributes::kCookie, &v)) {
    for (int i = 0, nv = v.size(); i < nv; ++i) {
      StringPieceVector cookies;
      SplitStringPieceToVector(*(v[i]), ";", &cookies, true);
      for (int j = 0, ncookies = cookies.size(); j < ncookies; ++j) {
        StringPiece cookie(cookies[j]);
        TrimWhitespace(&cookie);
        if (StringCaseStartsWith(cookie, kExperimentCookiePrefix)) {
          cookie.remove_prefix(STATIC_STRLEN(kExperimentCookiePrefix));
          *value = CookieStringToState(cookie);
          // If we got a bogus value for the cookie, keep looking for another
          // one just in case.
          if (*value != kExperimentNotSet) {
            return true;
          }
        }
      }
    }
  }
  return false;
}

void RemoveExperimentCookie(RequestHeaders* headers) {
  headers->RemoveCookie(kExperimentCookie);
}

void SetExperimentCookie(ResponseHeaders* headers,
                      int state,
                      const StringPiece& url,
                      int64 expiration_time_ms) {
  GoogleUrl request_url(url);
  // If we can't parse this url, don't try to set headers on the response.
  if (!request_url.IsWebValid()) {
    return;
  }
  GoogleString expires;
  ConvertTimeToString(expiration_time_ms, &expires);
  StringPiece host = request_url.Host();
  if (host.length() == 0) {
    return;
  }
  GoogleString value = StringPrintf(
      "%s=%s; Expires=%s; Domain=.%s; Path=/",
      kExperimentCookie, ExperimentStateToCookieString(state).c_str(),
      expires.c_str(), host.as_string().c_str());
  headers->Add(HttpAttributes::kSetCookie, value);
  headers->ComputeCaching();
}

// TODO(nforman): Is this a reasonable way of getting the appropriate
// percentage of the traffic?
// It might be "safer" to do this as a hash of ip so that if one person
// sent simultaneous requests, they would end up on the same side of the
// experiment for all requests.
int DetermineExperimentState(const RewriteOptions* options,
                             const RequestHeaders& request_headers,
                             const UserAgentMatcher& agent_matcher) {
  int ret = kExperimentNotSet;
  int num_experiments = options->num_experiments();

  // If are no experiments, return kExperimentNotSet so RewriteOptions doesn't
  // try to change.
  if (num_experiments < 1) {
    return ret;
  }

  const char* user_agent = request_headers.Lookup1(HttpAttributes::kUserAgent);
  UserAgentMatcher::DeviceType device_type =
      agent_matcher.GetDeviceTypeForUA(user_agent);

  int64 bound = 0;
  int64 index = random();
  ret = kNoExperiment;
  // One of these should be the control.
  for (int i = 0; i < num_experiments; ++i) {
    RewriteOptions::ExperimentSpec* spec = options->experiment_spec(i);
    double mult = static_cast<double>(spec->percent())/100.0;

    // Because RewriteOptions checks to make sure the total experiment
    // percentage is not greater than 100, bound should never be greater
    // than RAND_MAX.
    bound += (mult * RAND_MAX);
    if (index < bound) {
      // At this point we have determined the bucket for this request,
      // however that bucket may have a device type match condition.
      // In the case where the device type does not match, we still want
      // to break out of the loop, otherwise we will "overflow" into the
      // next bucket and mess up all the bucket size percentages.
      if (spec->matches_device_type(device_type)) {
        ret = spec->id();
      }
      return ret;
    }
  }
  return ret;
}

bool AnyActiveExperiments(const RewriteOptions* options) {
  for (int i = 0, n = options->num_experiments(); i < n ; ++i) {
    if (options->experiment_spec(i)->percent() > 0) {
      return true;
    }
  }
  return false;
}

int CookieStringToState(const StringPiece& cookie_str) {
  int ret;
  if (!StringToInt(cookie_str, &ret)) {
    ret = kExperimentNotSet;
  }
  return ret;
}

GoogleString ExperimentStateToCookieString(int state) {
  GoogleString cookie_value = IntegerToString(state);
  return cookie_value;
}


}  // namespace experiment

}  // namespace net_instaweb
