// Copyright 2019 The Flutter Authors. 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 'dart:io';

import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

import '../service/config.dart';
import '../service/logging.dart';

import 'body.dart';
import 'exceptions.dart';

/// A class that services HTTP requests and returns HTTP responses.
///
/// `T` is the type of object that is returned as the body of the HTTP response
/// (before serialization). Subclasses whose HTTP responses don't include a
/// body should extend `RequestHandler<Body>` and return null in their service
/// handlers ([get] and [post]).

abstract class RequestHandler<T extends Body> {
  /// Creates a new [RequestHandler].
  const RequestHandler({
    required this.config,
  });

  /// The global configuration of this AppEngine server.
  final Config config;

  /// Services an HTTP request.
  ///
  /// Subclasses should generally not override this method. Instead, they
  /// should override one of [get] or [post], depending on which methods
  /// they support.
  Future<void> service(
    HttpRequest request, {
    Future<void> Function(HttpStatusException)? onError,
  }) {
    return runZoned<Future<void>>(() async {
      final HttpResponse response = request.response;
      try {
        try {
          T body;
          switch (request.method) {
            case 'GET':
              body = await get();
              break;
            case 'POST':
              body = await post();
              break;
            default:
              throw MethodNotAllowed(request.method);
          }
          await _respond(body: body);
          httpClient?.close();
          return;
        } on HttpStatusException {
          rethrow;
        } catch (error, stackTrace) {
          log.severe('$error\n$stackTrace');
          throw InternalServerError('$error\n$stackTrace');
        }
      } on HttpStatusException catch (error) {
        if (onError != null) {
          await onError(error);
        }
        response
          ..statusCode = error.statusCode
          ..write(error.message);
        await response.flush();
        await response.close();
        return;
      }
    }, zoneValues: <RequestKey<dynamic>, Object>{
      RequestKey.request: request,
      RequestKey.response: request.response,
      RequestKey.httpClient: httpClient ?? http.Client(),
    });
  }

  /// Responds (using [response]) with the specified [status] and optional
  /// [body].
  ///
  /// Returns a future that completes when [response] has been closed.
  Future<void> _respond({int status = HttpStatus.ok, Body body = Body.empty}) async {
    response!.statusCode = status;
    await response!.addStream(body.serialize().cast<List<int>>());
    await response!.flush();
    await response!.close();
  }

  /// Gets the value associated with the specified [key] in the request
  /// context.
  ///
  /// Concrete subclasses should not call this directly. Instead, they should
  /// access the getters that are tied to specific keys, such as [request]
  /// and [response].
  ///
  /// If this is called outside the context of an HTTP request, this will
  /// throw a [StateError].
  @protected
  U? getValue<U>(RequestKey<U> key, {bool allowNull = false}) {
    final U? value = Zone.current[key] as U?;
    if (!allowNull && value == null) {
      throw StateError('Attempt to access ${key.name} while not in a request context');
    }
    return value;
  }

  /// Gets the current [HttpRequest].
  ///
  /// If this is called outside the context of an HTTP request, this will
  /// throw a [StateError].
  @protected
  HttpRequest? get request => getValue<HttpRequest>(RequestKey.request);

  /// Gets the current [HttpResponse].
  ///
  /// If this is called outside the context of an HTTP request, this will
  /// throw a [StateError].
  @protected
  HttpResponse? get response => getValue<HttpResponse>(RequestKey.response);

  /// Services an HTTP GET.
  ///
  /// Subclasses should override this method if they support GET requests.
  /// The default implementation will respond with HTTP 405 method not allowed.
  @protected
  Future<T> get() async {
    throw const MethodNotAllowed('GET');
  }

  /// Services an HTTP POST.
  ///
  /// Subclasses should override this method if they support POST requests.
  /// The default implementation will respond with HTTP 405 method not allowed.
  @protected
  Future<T> post() async {
    throw const MethodNotAllowed('POST');
  }

  /// The package:http Client to use for googleapis requests.
  @protected
  http.Client? get httpClient => getValue<http.Client>(
        RequestKey.httpClient,
        allowNull: true,
      );
}

/// A key that can be used to index a value within the request context.
///
/// Subclasses will only need to deal directly with this class if they add
/// their own request context values.
@protected
class RequestKey<T> {
  const RequestKey(this.name);

  final String name;

  static const RequestKey<HttpRequest> request = RequestKey<HttpRequest>('request');
  static const RequestKey<HttpResponse> response = RequestKey<HttpResponse>('response');
  static const RequestKey<http.Client> httpClient = RequestKey<http.Client>('httpClient');

  @override
  String toString() => '$runtimeType($name)';
}
