// Copyright (c) 2012, 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.

library utils;

import 'dart:io';
import 'dart:json';
import 'dart:uri';

import '../../unittest/lib/unittest.dart';
import '../lib/http.dart' as http;
import '../lib/src/utils.dart';

/// The current server instance.
HttpServer _server;

/// The URL for the current server instance.
Uri get serverUrl => new Uri.fromString('http://localhost:${_server.port}');

/// A dummy URL for constructing requests that won't be sent.
Uri get dummyUrl => new Uri.fromString('http://dartlang.org/');

/// Starts a new HTTP server.
void startServer() {
  _server = new HttpServer();

  _server.addRequestHandler((request) => request.path == '/error',
      (request, response) {
    response.statusCode = 400;
    response.contentLength = 0;
    response.outputStream.close();
  });

  _server.addRequestHandler((request) => request.path == '/loop',
      (request, response) {
    var n = int.parse(new Uri.fromString(request.uri).query);
    response.statusCode = 302;
    response.headers.set('location', '/loop?${n + 1}');
    response.contentLength = 0;
    response.outputStream.close();
  });

  _server.addRequestHandler((request) => request.path == '/redirect',
      (request, response) {
    response.statusCode = 302;
    response.headers.set('location', '/');
    response.contentLength = 0;
    response.outputStream.close();
  });

  _server.defaultRequestHandler = (request, response) {
    consumeInputStream(request.inputStream).then((requestBodyBytes) {
      response.statusCode = 200;
      response.headers.contentType = new ContentType("application", "json");

      var requestBody;
      if (requestBodyBytes.isEmpty) {
        requestBody = null;
      } else if (request.headers.contentType.charset != null) {
        var encoding = requiredEncodingForCharset(
            request.headers.contentType.charset);
        requestBody = decodeString(requestBodyBytes, encoding);
      } else {
        requestBody = requestBodyBytes;
      }

      var content = {
        'method': request.method,
        'path': request.path,
        'headers': <String>{}
      };
      if (requestBody != null) content['body'] = requestBody;
      request.headers.forEach((name, values) {
        // These headers are automatically generated by dart:io, so we don't
        // want to test them here.
        if (name == 'cookie' || name == 'host') return;

        content['headers'][name] = values;
      });

      var outputEncoding;
      var encodingName = request.queryParameters['response-encoding'];
      if (encodingName != null) {
        outputEncoding = requiredEncodingForCharset(encodingName);
      } else {
        outputEncoding = Encoding.ASCII;
      }

      var body = JSON.stringify(content);
      response.contentLength = body.length;
      response.outputStream.writeString(body, outputEncoding);
      response.outputStream.close();
    });
  };

  _server.listen("127.0.0.1", 0);
}

/// Stops the current HTTP server.
void stopServer() {
  _server.close();
  _server = null;
}

/// A matcher that matches JSON that parses to a value that matches the inner
/// matcher.
Matcher parse(matcher) => new _Parse(matcher);

class _Parse extends BaseMatcher {
  final Matcher _matcher;

  _Parse(this._matcher);

  bool matches(item, MatchState matchState) {
    if (item is! String) return false;

    var parsed;
    try {
      parsed = JSON.parse(item);
    } catch (e) {
      return false;
    }

    return _matcher.matches(parsed, matchState);
  }

  Description describe(Description description) {
    return description.add('parses to a value that ')
      .addDescriptionOf(_matcher);
  }
}

// TODO(nweiz): remove this once it's built in to unittest
/// A matcher for StateErrors.
const isStateError = const _StateError();

/// A matcher for functions that throw StateError.
const Matcher throwsStateError =
    const Throws(isStateError);

class _StateError extends TypeMatcher {
  const _StateError() : super("StateError");
  bool matches(item, MatchState matchState) => item is StateError;
}

/// A matcher for HttpExceptions.
const isHttpException = const _HttpException();

/// A matcher for functions that throw HttpException.
const Matcher throwsHttpException =
    const Throws(isHttpException);

class _HttpException extends TypeMatcher {
  const _HttpException() : super("HttpException");
  bool matches(item, MatchState matchState) => item is HttpException;
}

/// A matcher for RedirectLimitExceededExceptions.
const isRedirectLimitExceededException =
    const _RedirectLimitExceededException();

/// A matcher for functions that throw RedirectLimitExceededException.
const Matcher throwsRedirectLimitExceededException =
    const Throws(isRedirectLimitExceededException);

class _RedirectLimitExceededException extends TypeMatcher {
  const _RedirectLimitExceededException() :
      super("RedirectLimitExceededException");

  bool matches(item, MatchState matchState) =>
    item is RedirectLimitExceededException;
}
