// Copyright (c) 2014, 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:http/http.dart' as http;
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

Map<String, String> get _handshakeHeaders => {
      'Upgrade': 'websocket',
      'Connection': 'Upgrade',
      'Sec-WebSocket-Key': 'x3JJHMbDL1EzLkh9GBhXDw==',
      'Sec-WebSocket-Version': '13'
    };

void main() {
  test('can communicate with a dart:io WebSocket client', () async {
    final server = await shelf_io.serve(webSocketHandler((webSocket, _) {
      webSocket.sink.add('hello!');
      webSocket.stream.first.then((request) {
        expect(request, equals('ping'));
        webSocket.sink.add('pong');
        webSocket.sink.close();
      });
    }), 'localhost', 0);

    try {
      final webSocket =
          await WebSocket.connect('ws://localhost:${server.port}');
      var n = 0;
      await webSocket.listen((message) {
        if (n == 0) {
          expect(message, equals('hello!'));
          webSocket.add('ping');
        } else if (n == 1) {
          expect(message, equals('pong'));
          webSocket.close();
          server.close();
        } else {
          fail('Only expected two messages.');
        }
        n++;
      }).asFuture<void>();
    } finally {
      await server.close();
    }
  });

  test('negotiates the sub-protocol', () async {
    final server = await shelf_io.serve(
        webSocketHandler((WebSocketChannel webSocket, String? protocol) {
          expect(protocol, equals('two'));
          webSocket.sink.close();
        }, protocols: ['three', 'two', 'x']),
        'localhost',
        0);

    try {
      final webSocket = await WebSocket.connect('ws://localhost:${server.port}',
          protocols: ['one', 'two', 'three']);
      expect(webSocket.protocol, equals('two'));
      return webSocket.close();
    } finally {
      await server.close();
    }
  });

  test('handles protocol header without allowed protocols', () async {
    final server = await shelf_io.serve(webSocketHandler((webSocket, _) {
      webSocket.sink.close();
    }), 'localhost', 0);

    try {
      final webSocket = await WebSocket.connect('ws://localhost:${server.port}',
          protocols: ['one', 'two', 'three']);
      expect(webSocket.protocol, isNull);
      return webSocket.close();
    } finally {
      await server.close();
    }
  });

  test('allows two argument callbacks without protocols', () async {
    final server = await shelf_io.serve(
        webSocketHandler((WebSocketChannel webSocket, String? protocol) {
      expect(protocol, isNull);
      webSocket.sink.close();
    }), 'localhost', 0);

    try {
      final webSocket = await WebSocket.connect('ws://localhost:${server.port}',
          protocols: ['one', 'two', 'three']);
      expect(webSocket.protocol, isNull);
      return webSocket.close();
    } finally {
      await server.close();
    }
  });

  test('cannot hijack non-Socket StreamChannel', () async {
    final handler =
        webSocketHandler((WebSocketChannel webSocket, String? protocol) {
      expect(protocol, isNull);
      webSocket.sink.close();
    });

    expect(
        () => handler(Request('GET', Uri.parse('ws://example.com/'),
                protocolVersion: '1.1',
                headers: {
                  'Host': 'example.com',
                  'Upgrade': 'websocket',
                  'Connection': 'Upgrade',
                  'Sec-WebSocket-Key': 'x3JJHMbDL1EzLkh9GBhXDw==',
                  'Sec-WebSocket-Version': '13',
                  'Origin': 'http://example.com',
                }, onHijack: (fn) {
              // `.foreign` is not a Socket so hijacking the request should
              // fail.
              expect(() => fn(StreamChannelController<List<int>>().foreign),
                  throwsArgumentError);
            })),
        throwsA(isA<HijackException>()));
  });

  group('with a set of allowed origins', () {
    late HttpServer server;
    late Uri url;
    setUp(() async {
      server = await shelf_io.serve(
          webSocketHandler((webSocket, _) {
            webSocket.sink.close();
          }, allowedOrigins: ['pub.dartlang.org', 'GoOgLe.CoM']),
          'localhost',
          0);
      url = Uri.http('localhost:${server.port}', '');
    });

    tearDown(() => server.close());

    test('allows access with an allowed origin', () {
      final headers = _handshakeHeaders;
      headers['Origin'] = 'pub.dartlang.org';
      expect(http.get(url, headers: headers), hasStatus(101));
    });

    test('forbids access with a non-allowed origin', () {
      final headers = _handshakeHeaders;
      headers['Origin'] = 'dartlang.org';
      expect(http.get(url, headers: headers), hasStatus(403));
    });

    test('allows access with no origin', () {
      expect(http.get(url, headers: _handshakeHeaders), hasStatus(101));
    });

    test('ignores the case of the client origin', () {
      final headers = _handshakeHeaders;
      headers['Origin'] = 'PuB.DaRtLaNg.OrG';
      expect(http.get(url, headers: headers), hasStatus(101));
    });

    test('ignores the case of the server origin', () {
      final headers = _handshakeHeaders;
      headers['Origin'] = 'google.com';
      expect(http.get(url, headers: headers), hasStatus(101));
    });
  });

  // Regression test for issue 21894.
  test('allows a Connection header with multiple values', () async {
    final server = await shelf_io.serve(webSocketHandler((webSocket, _) {
      webSocket.sink.close();
    }), 'localhost', 0);

    final url = Uri.http('localhost:${server.port}', '');
    final headers = _handshakeHeaders;
    headers['Connection'] = 'Other-Token, Upgrade';
    expect(http.get(url, headers: headers).whenComplete(server.close),
        hasStatus(101));
  });

  group('HTTP errors', () {
    late HttpServer server;
    late Uri url;
    setUp(() async {
      server = await shelf_io.serve(webSocketHandler((_, __) {
        fail('should not create a WebSocket');
      }), 'localhost', 0);
      url = Uri.http('localhost:${server.port}', '');
    });

    tearDown(() => server.close());

    test('404s for non-GET requests', () {
      expect(http.delete(url, headers: _handshakeHeaders), hasStatus(404));
    });

    test('404s for non-Upgrade requests', () {
      final headers = _handshakeHeaders..remove('Connection');
      expect(http.get(url, headers: headers), hasStatus(404));
    });

    test('404s for non-websocket upgrade requests', () {
      final headers = _handshakeHeaders;
      headers['Upgrade'] = 'fblthp';
      expect(http.get(url, headers: headers), hasStatus(404));
    });

    test('400s for a missing Sec-WebSocket-Version', () {
      final headers = _handshakeHeaders..remove('Sec-WebSocket-Version');
      expect(http.get(url, headers: headers), hasStatus(400));
    });

    test('404s for an unknown Sec-WebSocket-Version', () {
      final headers = _handshakeHeaders;
      headers['Sec-WebSocket-Version'] = '15';
      expect(http.get(url, headers: headers), hasStatus(404));
    });

    test('400s for a missing Sec-WebSocket-Key', () {
      final headers = _handshakeHeaders..remove('Sec-WebSocket-Key');
      expect(http.get(url, headers: headers), hasStatus(400));
    });
  });
}

Matcher hasStatus(int status) => completion(predicate((http.Response response) {
      expect(response, isA<http.Response>());
      expect(response.statusCode, equals(status));
      return true;
    }));
