// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import "dart:io";

import "package:expect/expect.dart";

void testCookies() {
  var cookies = [
    {'abc': 'def'},
    {'ABC': 'DEF'},
    {'Abc': 'Def'},
    {'Abc': 'Def', 'SID': 'sffFSDF4FsdfF56765'}
  ];

  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((HttpRequest request) {
      // Collect the cookies in a map.
      var cookiesMap = {};
      request.cookies.forEach((c) => cookiesMap[c.name] = c.value);
      int index = int.parse(request.uri.path.substring(1));
      Expect.mapEquals(cookies[index], cookiesMap);
      // Return the same cookies to the client.
      cookiesMap.forEach((k, v) {
        request.response.cookies.add(new Cookie(k, v));
      });
      request.response.close();
    });

    int count = 0;
    HttpClient client = new HttpClient();
    for (int i = 0; i < cookies.length; i++) {
      client.get("127.0.0.1", server.port, "/$i").then((request) {
        // Send the cookies to the server.
        cookies[i].forEach((k, v) {
          request.cookies.add(new Cookie(k, v));
        });
        return request.close();
      }).then((response) {
        // Expect the same cookies back.
        var cookiesMap = {};
        response.cookies.forEach((c) => cookiesMap[c.name] = c.value);
        Expect.mapEquals(cookies[i], cookiesMap);
        response.cookies.forEach((c) => Expect.isTrue(c.httpOnly));
        response.listen((d) {}, onDone: () {
          if (++count == cookies.length) {
            client.close();
            server.close();
          }
        });
      }).catchError((e, trace) {
        String msg = "Unexpected error $e";
        if (trace != null) msg += "\nStackTrace: $trace";
        Expect.fail(msg);
      });
    }
  });
}

void testValidateCookieWithDoubleQuotes() {
  Expect.equals(Cookie('key', 'value').toString(), 'key=value; HttpOnly');
  Expect.equals(Cookie('key', '').toString(), 'key=; HttpOnly');
  Expect.equals(Cookie('key', '""').toString(), 'key=""; HttpOnly');
  Expect.equals(Cookie('key', '"value"').toString(), 'key="value"; HttpOnly');
  Expect.equals(Cookie.fromSetCookieValue('key=value; HttpOnly').toString(),
      'key=value; HttpOnly');
  Expect.equals(
      Cookie.fromSetCookieValue('key=; HttpOnly').toString(), 'key=; HttpOnly');
  Expect.equals(Cookie.fromSetCookieValue('key=""; HttpOnly').toString(),
      'key=""; HttpOnly');
  Expect.equals(Cookie.fromSetCookieValue('key="value"; HttpOnly').toString(),
      'key="value"; HttpOnly');
  Expect.throwsFormatException(() => Cookie('key', '"'));
  Expect.throwsFormatException(() => Cookie('key', '"""'));
  Expect.throwsFormatException(() => Cookie('key', '"x""'));
  Expect.throwsFormatException(() => Cookie('key', '"x"y"'));
  Expect.throwsFormatException(
      () => Cookie.fromSetCookieValue('key="; HttpOnly'));
  Expect.throwsFormatException(
      () => Cookie.fromSetCookieValue('key="""; HttpOnly'));
  Expect.throwsFormatException(
      () => Cookie.fromSetCookieValue('key="x""; HttpOnly'));
}

void testValidatePath() {
  Cookie cookie = Cookie.fromSetCookieValue(" cname = cval; path= / ");
  Expect.equals('/', cookie.path);
  cookie.path = null;
  Expect.throws<FormatException>(() {
    cookie.path = "something; ";
  }, (e) => e.toString().contains('Invalid character'));

  StringBuffer buffer = StringBuffer();
  buffer.writeCharCode(0x1f);
  Expect.throws<FormatException>(() {
    cookie.path = buffer.toString();
  }, (e) => e.toString().contains('Invalid character'));

  buffer.clear();
  buffer.writeCharCode(0x7f);
  Expect.throws<FormatException>(() {
    cookie.path = buffer.toString();
  }, (e) => e.toString().contains('Invalid character'));

  buffer.clear();
  buffer.writeCharCode(0x00);
  Expect.throws<FormatException>(() {
    cookie.path = buffer.toString();
  }, (e) => e.toString().contains('Invalid character'));
}

void testCookieSameSite() {
  Cookie cookie1 = Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; Secure; "
          "HttpOnly; Path=/; SameSite=None");
  Expect.equals(cookie1.sameSite, SameSite.none);
  Cookie cookie2 = Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; SameSite=Lax");
  Expect.equals(cookie2.sameSite, SameSite.lax);
  Cookie cookie3 = Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; SameSite=LAX");
  Expect.equals(cookie3.sameSite, SameSite.lax);
  Cookie cookie4 = Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; SameSite= Lax");
  Expect.equals(cookie4.sameSite, SameSite.lax);
  Cookie cookie5 = Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; sAmEsItE= nOnE");
  Expect.equals(cookie5.sameSite, SameSite.none);
  Expect.throws<HttpException>(() => Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; SameSite=Relax"),
      (e) => e.message == "SameSite value should be one of Lax, Strict or None.");
  Expect.throws<HttpException>(() => Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; SameSite="),
      (e) => e.message == "SameSite value should be one of Lax, Strict or None.");
  Expect.throws<HttpException>(() => Cookie.fromSetCookieValue(
      "name=cookie_name; Expires=Sat, 01 Apr 2023 00:00:00 GMT; HttpOnly; "
          "Path=/; SameSite=无"),
      (e) => e.message == "SameSite value should be one of Lax, Strict or None.");
}

void main() {
  testCookies();
  testValidateCookieWithDoubleQuotes();
  testValidatePath();
  testCookieSameSite();
}
