// Copyright (c) 2017, 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 'dart:convert';
import 'dart:io';

import 'package:intl/intl.dart';

final NumberFormat numberFormat = new NumberFormat.decimalPattern();

String escape(String text) => text == null ? '' : htmlEscape.convert(text);

String printInteger(int value) => numberFormat.format(value);

String printMilliseconds(num value) => '${numberFormat.format(value)} ms';

String printPercentage(num value) => '${(value * 100).toStringAsFixed(1)}%';

/// An entity that knows how to serve itself over http.
abstract class Page {
  final StringBuffer buf = new StringBuffer();

  final String id;
  final String title;
  final String description;

  Page(this.id, this.title, {this.description});

  String get path => '/$id';

  Future<Null> asyncDiv(void gen(), {String classes}) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    if (classes != null) {
      buf.writeln('<div class="$classes">');
    } else {
      buf.writeln('<div>');
    }
    // TODO(brianwilkerson) Determine if await is necessary, if so, change the
    // return type of [gen] to `Future<void>`.
    await (gen() as dynamic);
    buf.writeln('</div>');
  }

  void blankslate(String str) {
    div(() => buf.writeln(str), classes: 'blankslate');
  }

  void div(void gen(), {String classes}) {
    if (classes != null) {
      buf.writeln('<div class="$classes">');
    } else {
      buf.writeln('<div>');
    }
    gen();
    buf.writeln('</div>');
  }

  Future<String> generate(Map<String, String> params) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    buf.clear();
    // TODO(brianwilkerson) Determine if await is necessary, if so, change the
    // return type of [generatePage] to `Future<void>`.
    await (generatePage(params) as dynamic);
    return buf.toString();
  }

  void generatePage(Map<String, String> params);

  void h1(String text, {String classes}) {
    if (classes != null) {
      buf.writeln('<h1 class="$classes">${escape(text)}</h1>');
    } else {
      buf.writeln('<h1>${escape(text)}</h1>');
    }
  }

  void h2(String text) {
    buf.writeln('<h2>${escape(text)}</h2>');
  }

  void h3(String text, {bool raw: false}) {
    buf.writeln('<h3>${raw ? text : escape(text)}</h3>');
  }

  void h4(String text, {bool raw: false}) {
    buf.writeln('<h4>${raw ? text : escape(text)}</h4>');
  }

  void inputList<T>(Iterable<T> items, void gen(T item)) {
    buf.writeln('<select size="8" style="width: 100%">');
    for (T item in items) {
      buf.write('<option>');
      gen(item);
      buf.write('</option>');
    }
    buf.writeln('</select>');
  }

  bool isCurrentPage(String pathToTest) => path == pathToTest;

  void p(String text, {String style, bool raw: false, String classes}) {
    String c = classes == null ? '' : ' class="$classes"';

    if (style != null) {
      buf.writeln('<p$c style="$style">${raw ? text : escape(text)}</p>');
    } else {
      buf.writeln('<p$c>${raw ? text : escape(text)}</p>');
    }
  }

  void pre(void gen(), {String classes}) {
    if (classes != null) {
      buf.write('<pre class="$classes">');
    } else {
      buf.write('<pre>');
    }
    gen();
    buf.writeln('</pre>');
  }

  void ul<T>(Iterable<T> items, void gen(T item), {String classes}) {
    buf.writeln('<ul${classes == null ? '' : ' class=$classes'}>');
    for (T item in items) {
      buf.write('<li>');
      gen(item);
      buf.write('</li>');
    }
    buf.writeln('</ul>');
  }
}

/// Contains a collection of Pages.
abstract class Site {
  final String title;
  List<Page> pages = [];

  Site(this.title);

  String get customCss => '';

  Page createExceptionPage(String message, StackTrace trace);

  Page createUnknownPage(String unknownPath);

  Future<Null> handleGetRequest(HttpRequest request) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    try {
      String path = request.uri.path;

      if (path == '/') {
        respondRedirect(request, pages.first.path);
        return;
      }

      for (Page page in pages) {
        if (page.path == path) {
          HttpResponse response = request.response;
          response.headers.contentType = ContentType.html;
          response.write(await page.generate(request.uri.queryParameters));
          response.close();
          return;
        }
      }

      await respond(request, createUnknownPage(path), HttpStatus.notFound);
    } catch (e, st) {
      try {
        await respond(request, createExceptionPage('$e', st),
            HttpStatus.internalServerError);
      } catch (e, st) {
        HttpResponse response = request.response;
        response.statusCode = HttpStatus.internalServerError;
        response.headers.contentType = ContentType.text;
        response.write('$e\n\n$st');
        response.close();
      }
    }
  }

  Future<Null> respond(HttpRequest request, Page page,
      [int code = HttpStatus.ok]) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    HttpResponse response = request.response;
    response.statusCode = code;
    response.headers.contentType = ContentType.html;
    response.write(await page.generate(request.uri.queryParameters));
    response.close();
  }

  void respondRedirect(HttpRequest request, String pathFragment) {
    HttpResponse response = request.response;
    response.statusCode = HttpStatus.movedTemporarily;
    response.redirect(request.uri.resolve(pathFragment));
  }
}
