// 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.

library shelf.server_handler;

import 'dart:async';

import 'package:async/async.dart';

import 'request.dart';
import 'handler.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 = new _HandlerServer(url, onClose);

  /// Pipes requests to [server]'s handler.
  _onRequest(Request request) {
    if (_server._closeMemo.hasRun) {
      throw new 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 = new Completer();

  _HandlerServer(this.url, this._onClose);

  void mount(Handler handler) {
    if (_handler != null) {
      throw new 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 = new AsyncMemoizer();
}
