// Copyright (c) 2015, 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:async';

import 'package:async/async.dart';

import 'handler.dart';
import 'request.dart';
import 'response.dart';
import 'server.dart';

/// A connected pair of a [Server] and a [Handler].
///
/// Requests to the handler are sent to the server's mounted handler once it's
/// available. This is used to expose a virtual [Server] that's actually one
/// part of a larger URL-space.
class ServerHandler {
  /// The server.
  ///
  /// Once this has a handler mounted, it's passed all requests to [handler]
  /// until this server is closed.
  Server get server => _server;
  final _HandlerServer _server;

  /// The handler.
  ///
  /// This passes requests to [server]'s handler. If that handler isn't mounted
  /// yet, the requests are handled once it is.
  Handler get handler => _onRequest;

  /// Creates a new connected pair of a [Server] with the given [url] and a
  /// [Handler].
  ///
  /// The caller is responsible for ensuring that requests to [url] or any URL
  /// beneath it are handled by [handler].
  ///
  /// If [onClose] is passed, it's called when [server] is closed. It may return
  /// a [Future] or `null`; its return value is returned by [Server.close].
  ServerHandler(Uri url, {onClose()}) : _server = _HandlerServer(url, onClose);

  /// Pipes requests to [server]'s handler.
  FutureOr<Response> _onRequest(Request request) {
    if (_server._closeMemo.hasRun) {
      throw StateError("Request received after the server was closed.");
    }

    if (_server._handler != null) return _server._handler(request);

    // Avoid async/await so that the common case of a handler already being
    // mounted doesn't involve any extra asynchronous delays.
    return _server._onMounted.then((_) => _server._handler(request));
  }
}

/// The [Server] returned by [ServerHandler].
class _HandlerServer implements Server {
  final Uri url;

  /// The callback to call when [close] is called, or `null`.
  final ZoneCallback _onClose;

  /// The mounted handler.
  ///
  /// This is `null` until [mount] is called.
  Handler _handler;

  /// A future that fires once [mount] has been called.
  Future get _onMounted => _onMountedCompleter.future;
  final _onMountedCompleter = Completer();

  _HandlerServer(this.url, this._onClose);

  void mount(Handler handler) {
    if (_handler != null) {
      throw StateError("Can't mount two handlers for the same server.");
    }

    _handler = handler;
    _onMountedCompleter.complete();
  }

  Future close() => _closeMemo.runOnce(() {
        return _onClose == null ? null : _onClose();
      });
  final _closeMemo = AsyncMemoizer();
}
