/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
// Ideally, we would rely on platform support for parsing a cookie, since
// this would save us from any potential inconsistency. However, exposing
// platform cookie parsing logic would require quite a bit of additional
// plumbing, and at least some platforms lack support for parsing Cookie,
// which is in a format slightly different from Set-Cookie and is normally
// only required on the server side.

/**
 * @unrestricted
 */
SDK.CookieParser = class {
  /**
   * @param {!SDK.Target} target
   */
  constructor(target) {
    this._target = target;
  }

  /**
   * @param {!SDK.Target} target
   * @param {string|undefined} header
   * @return {?Array.<!SDK.Cookie>}
   */
  static parseCookie(target, header) {
    return (new SDK.CookieParser(target)).parseCookie(header);
  }

  /**
   * @param {!SDK.Target} target
   * @param {string|undefined} header
   * @return {?Array.<!SDK.Cookie>}
   */
  static parseSetCookie(target, header) {
    return (new SDK.CookieParser(target)).parseSetCookie(header);
  }

  /**
   * @return {!Array.<!SDK.Cookie>}
   */
  cookies() {
    return this._cookies;
  }

  /**
   * @param {string|undefined} cookieHeader
   * @return {?Array.<!SDK.Cookie>}
   */
  parseCookie(cookieHeader) {
    if (!this._initialize(cookieHeader))
      return null;

    for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
      if (kv.key.charAt(0) === '$' && this._lastCookie)
        this._lastCookie.addAttribute(kv.key.slice(1), kv.value);
      else if (kv.key.toLowerCase() !== '$version' && typeof kv.value === 'string')
        this._addCookie(kv, SDK.Cookie.Type.Request);
      this._advanceAndCheckCookieDelimiter();
    }
    this._flushCookie();
    return this._cookies;
  }

  /**
   * @param {string|undefined} setCookieHeader
   * @return {?Array.<!SDK.Cookie>}
   */
  parseSetCookie(setCookieHeader) {
    if (!this._initialize(setCookieHeader))
      return null;
    for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
      if (this._lastCookie)
        this._lastCookie.addAttribute(kv.key, kv.value);
      else
        this._addCookie(kv, SDK.Cookie.Type.Response);
      if (this._advanceAndCheckCookieDelimiter())
        this._flushCookie();
    }
    this._flushCookie();
    return this._cookies;
  }

  /**
   * @param {string|undefined} headerValue
   * @return {boolean}
   */
  _initialize(headerValue) {
    this._input = headerValue;
    if (typeof headerValue !== 'string')
      return false;
    this._cookies = [];
    this._lastCookie = null;
    this._originalInputLength = this._input.length;
    return true;
  }

  _flushCookie() {
    if (this._lastCookie)
      this._lastCookie.setSize(this._originalInputLength - this._input.length - this._lastCookiePosition);
    this._lastCookie = null;
  }

  /**
   * @return {?SDK.CookieParser.KeyValue}
   */
  _extractKeyValue() {
    if (!this._input || !this._input.length)
      return null;
    // Note: RFCs offer an option for quoted values that may contain commas and semicolons.
    // Many browsers/platforms do not support this, however (see http://webkit.org/b/16699
    // and http://crbug.com/12361). The logic below matches latest versions of IE, Firefox,
    // Chrome and Safari on some old platforms. The latest version of Safari supports quoted
    // cookie values, though.
    var keyValueMatch = /^[ \t]*([^\s=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this._input);
    if (!keyValueMatch) {
      console.log('Failed parsing cookie header before: ' + this._input);
      return null;
    }

    var result = new SDK.CookieParser.KeyValue(
        keyValueMatch[1], keyValueMatch[2] && keyValueMatch[2].trim(), this._originalInputLength - this._input.length);
    this._input = this._input.slice(keyValueMatch[0].length);
    return result;
  }

  /**
   * @return {boolean}
   */
  _advanceAndCheckCookieDelimiter() {
    var match = /^\s*[\n;]\s*/.exec(this._input);
    if (!match)
      return false;
    this._input = this._input.slice(match[0].length);
    return match[0].match('\n') !== null;
  }

  /**
   * @param {!SDK.CookieParser.KeyValue} keyValue
   * @param {!SDK.Cookie.Type} type
   */
  _addCookie(keyValue, type) {
    if (this._lastCookie)
      this._lastCookie.setSize(keyValue.position - this._lastCookiePosition);
    // Mozilla bug 169091: Mozilla, IE and Chrome treat single token (w/o "=") as
    // specifying a value for a cookie with empty name.
    this._lastCookie = typeof keyValue.value === 'string' ?
        new SDK.Cookie(this._target, keyValue.key, keyValue.value, type) :
        new SDK.Cookie(this._target, '', keyValue.key, type);
    this._lastCookiePosition = keyValue.position;
    this._cookies.push(this._lastCookie);
  }
};

/**
 * @unrestricted
 */
SDK.CookieParser.KeyValue = class {
  /**
   * @param {string} key
   * @param {string|undefined} value
   * @param {number} position
   */
  constructor(key, value, position) {
    this.key = key;
    this.value = value;
    this.position = position;
  }
};


/**
 * @unrestricted
 */
SDK.Cookie = class {
  /**
   * @param {!SDK.Target} target
   * @param {string} name
   * @param {string} value
   * @param {?SDK.Cookie.Type} type
   */
  constructor(target, name, value, type) {
    this._target = target;
    this._name = name;
    this._value = value;
    this._type = type;
    this._attributes = {};
  }

  /**
   * @return {string}
   */
  name() {
    return this._name;
  }

  /**
   * @return {string}
   */
  value() {
    return this._value;
  }

  /**
   * @return {?SDK.Cookie.Type}
   */
  type() {
    return this._type;
  }

  /**
   * @return {boolean}
   */
  httpOnly() {
    return 'httponly' in this._attributes;
  }

  /**
   * @return {boolean}
   */
  secure() {
    return 'secure' in this._attributes;
  }

  /**
   * @return {string}
   */
  sameSite() {
    return this._attributes['samesite'];
  }

  /**
   * @return {boolean}
   */
  session() {
    // RFC 2965 suggests using Discard attribute to mark session cookies, but this does not seem to be widely used.
    // Check for absence of explicitly max-age or expiry date instead.
    return !('expires' in this._attributes || 'max-age' in this._attributes);
  }

  /**
   * @return {string}
   */
  path() {
    return this._attributes['path'];
  }

  /**
   * @return {string}
   */
  port() {
    return this._attributes['port'];
  }

  /**
   * @return {string}
   */
  domain() {
    return this._attributes['domain'];
  }

  /**
   * @return {string}
   */
  expires() {
    return this._attributes['expires'];
  }

  /**
   * @return {string}
   */
  maxAge() {
    return this._attributes['max-age'];
  }

  /**
   * @return {number}
   */
  size() {
    return this._size;
  }

  /**
   * @param {number} size
   */
  setSize(size) {
    this._size = size;
  }

  /**
   * @return {?Date}
   */
  expiresDate(requestDate) {
    // RFC 6265 indicates that the max-age attribute takes precedence over the expires attribute
    if (this.maxAge()) {
      var targetDate = requestDate === null ? new Date() : requestDate;
      return new Date(targetDate.getTime() + 1000 * this.maxAge());
    }

    if (this.expires())
      return new Date(this.expires());

    return null;
  }

  /**
   * @return {!Object}
   */
  attributes() {
    return this._attributes;
  }

  /**
   * @param {string} key
   * @param {string=} value
   */
  addAttribute(key, value) {
    this._attributes[key.toLowerCase()] = value;
  }

  /**
   * @param {function(?Protocol.Error)=} callback
   */
  remove(callback) {
    this._target.networkAgent().deleteCookie(
        this.name(), (this.secure() ? 'https://' : 'http://') + this.domain() + this.path(), callback);
  }
};

/**
 * @enum {number}
 */
SDK.Cookie.Type = {
  Request: 0,
  Response: 1
};

SDK.Cookies = {};

/**
 * @param {function(!Array.<!SDK.Cookie>)} callback
 */
SDK.Cookies.getCookiesAsync = function(callback) {
  var allCookies = [];
  /**
   * @param {!SDK.Target} target
   * @param {?Protocol.Error} error
   * @param {!Array.<!Protocol.Network.Cookie>} cookies
   */
  function mycallback(target, error, cookies) {
    if (error) {
      console.error(error);
      return;
    }
    for (var i = 0; i < cookies.length; ++i)
      allCookies.push(SDK.Cookies._parseProtocolCookie(target, cookies[i]));
  }

  var barrier = new CallbackBarrier();
  for (var target of SDK.targetManager.targets(SDK.Target.Capability.Network)) {
    var global = false;
    target.networkAgent().getCookies(global, barrier.createCallback(mycallback.bind(null, target)));
  }
  barrier.callWhenDone(callback.bind(null, allCookies));
};

/**
 * @param {!SDK.Target} target
 * @param {!Protocol.Network.Cookie} protocolCookie
 * @return {!SDK.Cookie}
 */
SDK.Cookies._parseProtocolCookie = function(target, protocolCookie) {
  var cookie = new SDK.Cookie(target, protocolCookie.name, protocolCookie.value, null);
  cookie.addAttribute('domain', protocolCookie['domain']);
  cookie.addAttribute('path', protocolCookie['path']);
  cookie.addAttribute('port', protocolCookie['port']);
  if (protocolCookie['expires'])
    cookie.addAttribute('expires', protocolCookie['expires']);
  if (protocolCookie['httpOnly'])
    cookie.addAttribute('httpOnly');
  if (protocolCookie['secure'])
    cookie.addAttribute('secure');
  if (protocolCookie['sameSite'])
    cookie.addAttribute('sameSite', protocolCookie['sameSite']);
  cookie.setSize(protocolCookie['size']);
  return cookie;
};

/**
 * @param {!SDK.Cookie} cookie
 * @param {string} resourceURL
 * @return {boolean}
 */
SDK.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL) {
  var url = resourceURL.asParsedURL();
  if (!url || !SDK.Cookies.cookieDomainMatchesResourceDomain(cookie.domain(), url.host))
    return false;
  return (
      url.path.startsWith(cookie.path()) && (!cookie.port() || url.port === cookie.port()) &&
      (!cookie.secure() || url.scheme === 'https'));
};

/**
 * @param {string} cookieDomain
 * @param {string} resourceDomain
 * @return {boolean}
 */
SDK.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain) {
  if (cookieDomain.charAt(0) !== '.')
    return resourceDomain === cookieDomain;
  return !!resourceDomain.match(new RegExp('^([^\\.]+\\.)*' + cookieDomain.substring(1).escapeForRegExp() + '$', 'i'));
};
