// Copyright (c) 2016, 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 'dart:typed_data';

import 'package:path/path.dart' as p;
import 'package:pub/src/crc32c.dart';
import 'package:pub/src/source/hosted.dart';
import 'package:pub/src/third_party/tar/tar.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:test/test.dart';
import 'package:test/test.dart' as test show expect;

import 'descriptor.dart' as d;
import 'test_pub.dart';

class PackageServer {
  /// The inner [IOServer] that this uses to serve its descriptors.
  final shelf_io.IOServer _inner;

  /// Handlers of requests. Last matching handler will be used.
  final List<_PatternAndHandler> _handlers = [];

  // A list of all the requests recieved up till now.
  final List<String> requestedPaths = <String>[];

  /// Whether the [IOServer] should compress the content, if possible.
  /// The default value is `false` (compression disabled).
  /// See [HttpServer.autoCompress] for details.
  bool get autoCompress => _inner.server.autoCompress;
  set autoCompress(bool shouldAutoCompress) =>
      _inner.server.autoCompress = shouldAutoCompress;

  // Setting this to false will disable automatic calculation of checksums.
  bool serveChecksums = true;

  PackageServer._(this._inner) {
    _inner.mount((request) {
      final path = request.url.path;
      requestedPaths.add(path);

      final pathWithInitialSlash = '/$path';
      for (final entry in _handlers.reversed) {
        final match = entry.pattern.matchAsPrefix(pathWithInitialSlash);
        if (match != null && match.end == pathWithInitialSlash.length) {
          final a = entry.handler(request);
          return a;
        }
      }
      return shelf.Response.notFound('Could not find ${request.url}');
    });
  }

  static final _versionInfoPattern = RegExp(r'/api/packages/([a-zA-Z_0-9]*)');
  static final _downloadPattern =
      RegExp(r'/packages/([^/]*)/versions/([^/]*).tar.gz');

  static Future<PackageServer> start() async {
    final server =
        PackageServer._(await shelf_io.IOServer.bind('localhost', 0));
    server.handle(
      _versionInfoPattern,
      (shelf.Request request) {
        final parts = request.url.pathSegments;
        assert(parts[0] == 'api');
        assert(parts[1] == 'packages');
        final name = parts[2];

        final package = server._packages[name];
        if (package == null) {
          return shelf.Response.notFound('No package named $name');
        }
        return shelf.Response.ok(
            jsonEncode({
              'name': name,
              'uploaders': ['nweiz@google.com'],
              'versions': package.versions.values
                  .map((version) => packageVersionApiMap(
                        server._inner.url.toString(),
                        version.pubspec,
                        retracted: version.isRetracted,
                      ))
                  .toList(),
              if (package.isDiscontinued) 'isDiscontinued': true,
              if (package.discontinuedReplacementText != null)
                'replacedBy': package.discontinuedReplacementText,
            }),
            headers: {
              HttpHeaders.contentTypeHeader: 'application/vnd.pub.v2+json'
            });
      },
    );

    server.handle(
      _downloadPattern,
      (shelf.Request request) async {
        final parts = request.url.pathSegments;
        assert(parts[0] == 'packages');
        final name = parts[1];
        assert(parts[2] == 'versions');
        final package = server._packages[name];
        if (package == null) {
          return shelf.Response.notFound('No package $name');
        }

        final version = Version.parse(
            parts[3].substring(0, parts[3].length - '.tar.gz'.length));
        assert(parts[3].endsWith('.tar.gz'));

        for (final packageVersion in package.versions.values) {
          if (packageVersion.version == version) {
            final headers = packageVersion.headers ?? {};
            headers[HttpHeaders.contentTypeHeader] ??= [
              'application/octet-stream'
            ];

            // This gate enables tests to validate the CRC32C parser by
            // passing in arbitrary values for the checksum header.
            if (server.serveChecksums &&
                !headers.containsKey(checksumHeaderName)) {
              headers[checksumHeaderName] = composeChecksumHeader(
                  crc32c: await packageVersion.computeArchiveCrc32c());
            }

            return shelf.Response.ok(packageVersion.contents(),
                headers: headers);
          }
        }
        return shelf.Response.notFound('No version $version of $name');
      },
    );
    return server;
  }

  Future<void> close() async {
    await _inner.close();
  }

  /// The port used for the server.
  int get port => _inner.url.port;

  /// The URL for the server.
  String get url => _inner.url.toString();

  /// From now on report errors on any request.
  void serveErrors() => _handlers
    ..clear()
    ..add(
      _PatternAndHandler(
        RegExp('.*'),
        (request) {
          fail('The HTTP server received an unexpected request:\n'
              '${request.method} ${request.requestedUri}');
        },
      ),
    );

  void handle(Pattern pattern, shelf.Handler handler) {
    _handlers.add(
      _PatternAndHandler(
        pattern,
        handler,
      ),
    );
  }

  // Installs a handler at [pattern] that expects to be called exactly once with
  // the given [method].
  //
  // The handler is installed as the start to give it priority over more general
  // handlers.
  void expect(String method, Pattern pattern, shelf.Handler handler) {
    handle(
      pattern,
      expectAsync1(
        (request) {
          test.expect(request.method, method);
          return handler(request);
        },
      ),
    );
  }

  /// Returns the path of [package] at [version], installed from this server, in
  /// the pub cache.
  String pathInCache(String package, String version) =>
      p.join(cachingPath, '$package-$version');

  /// The location where pub will store the cache for this server.
  String get cachingPath =>
      p.join(d.sandbox, cachePath, 'hosted', 'localhost%58$port');

  /// A map from package names to the concrete packages to serve.
  final _packages = <String, _ServedPackage>{};

  /// Specifies that a package named [name] with [version] should be served.
  ///
  /// If [deps] is passed, it's used as the "dependencies" field of the pubspec.
  /// If [pubspec] is passed, it's used as the rest of the pubspec.
  ///
  /// If [contents] is passed, it's used as the contents of the package. By
  /// default, a package just contains a dummy lib directory.
  void serve(String name, String version,
      {Map<String, dynamic>? deps,
      Map<String, dynamic>? pubspec,
      List<d.Descriptor>? contents,
      Map<String, List<String>>? headers}) {
    var pubspecFields = <String, dynamic>{'name': name, 'version': version};
    if (pubspec != null) pubspecFields.addAll(pubspec);
    if (deps != null) pubspecFields['dependencies'] = deps;

    contents ??= [d.libDir(name, '$name $version')];
    contents = [d.file('pubspec.yaml', yaml(pubspecFields)), ...contents];

    var package = _packages.putIfAbsent(name, _ServedPackage.new);
    package.versions[version] = _ServedPackageVersion(
      pubspecFields,
      headers: headers,
      contents: () {
        final entries = <TarEntry>[];

        void addDescriptor(d.Descriptor descriptor, String path) {
          if (descriptor is d.DirectoryDescriptor) {
            for (final e in descriptor.contents) {
              addDescriptor(e, p.posix.join(path, descriptor.name));
            }
          } else {
            entries.add(
              TarEntry(
                TarHeader(
                  // Ensure paths in tar files use forward slashes
                  name: p.posix.join(path, descriptor.name),
                  // We want to keep executable bits, but otherwise use the default
                  // file mode
                  mode: 420,
                  // size: 100,
                  modified: DateTime.now(),
                  userName: 'pub',
                  groupName: 'pub',
                ),
                (descriptor as d.FileDescriptor).readAsBytes(),
              ),
            );
          }
        }

        for (final e in contents ?? <d.Descriptor>[]) {
          addDescriptor(e, '');
        }
        return Stream.fromIterable(entries)
            .transform(tarWriterWith(format: OutputFormat.gnuLongName))
            .transform(gzip.encoder);
      },
    );
  }

  // Mark a package discontinued.
  void discontinue(String name,
      {bool isDiscontinued = true, String? replacementText}) {
    _packages[name]!
      ..isDiscontinued = isDiscontinued
      ..discontinuedReplacementText = replacementText;
  }

  /// Clears all existing packages from this builder.
  void clearPackages() {
    _packages.clear();
  }

  void retractPackageVersion(String name, String version) {
    _packages[name]!.versions[version]!.isRetracted = true;
  }

  Future<String?> peekArchiveChecksumHeader(String name, String version) async {
    final v = _packages[name]!.versions[version]!;

    // If the test configured an overriding header value.
    var checksumHeader = v.headers?[checksumHeaderName];

    // Otherwise, compute from package contents.
    if (serveChecksums) {
      checksumHeader ??=
          composeChecksumHeader(crc32c: await v.computeArchiveCrc32c());
    }

    return checksumHeader?.join(',');
  }

  static List<String> composeChecksumHeader(
      {int? crc32c, String? md5 = '5f4dcc3b5aa765d61d8327deb882cf99'}) {
    List<String> header = [];

    if (crc32c != null) {
      final bytes = Uint8List(4)..buffer.asByteData().setUint32(0, crc32c);
      header.add('crc32c=${base64.encode(bytes)}');
    }

    if (md5 != null) {
      header.add('md5=${base64.encode(utf8.encode(md5))}');
    }

    return header;
  }
}

class _ServedPackage {
  final versions = <String, _ServedPackageVersion>{};
  bool isDiscontinued = false;
  String? discontinuedReplacementText;
}

/// A package that's intended to be served.
class _ServedPackageVersion {
  final Map pubspec;
  final Stream<List<int>> Function() contents;
  final Map<String, List<String>>? headers;
  bool isRetracted = false;

  Version get version => Version.parse(pubspec['version']);

  _ServedPackageVersion(this.pubspec, {required this.contents, this.headers});

  Future<int> computeArchiveCrc32c() async {
    return await Crc32c.computeByConsumingStream(contents());
  }
}

class _PatternAndHandler {
  Pattern pattern;
  shelf.Handler handler;

  _PatternAndHandler(this.pattern, this.handler);
}
