// 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:convert';
import 'dart:io';

import 'package:fuchsia_ctl/fuchsia_ctl.dart';
import 'package:process/process.dart';

/// A wrapper around the Fuchsia SDK `pm` tool.
class PackageServer {
  /// Creates a new package server.
  PackageServer(
    this.pmPath, {
    this.processManager = const LocalProcessManager(),
  })  : assert(pmPath != null),
        assert(processManager != null);

  /// The path on the file system to the `pm` executable.
  final String pmPath;

  /// The process manager to use for launching `pm`.
  final ProcessManager processManager;

  Process _pmServerProcess;

  /// The port the server is listening on, if the server is running.
  ///
  /// Throws a [StateError] if accessed when the server is not running.
  int get serverPort {
    if (_pmServerProcess == null) {
      throw StateError('Attempted to get port before starting server.');
    }
    return _serverPort;
  }

  int _serverPort;

  /// Is the server up?
  bool get serving {
    return _pmServerProcess != null;
  }

  /// Creates a new local repository and associated key material.
  ///
  /// Corresponds to `pm newrepo`.
  Future<OperationResult> newRepo(String repo) async {
    return OperationResult.fromProcessResult(
      await processManager.run(
        <String>[
          pmPath,
          'newrepo',
          '-repo', repo, //
        ],
      ),
    );
  }

  /// Publishes an archive package for use on a device with the specified
  /// .far files.
  Future<OperationResult> publishRepo(String repo, String farFile) async {
    return OperationResult.fromProcessResult(
      await processManager.run(
        <String>[
          pmPath,
          'publish',
          '-a',
          '-repo', repo, //
          '-f', farFile,
        ],
      ),
    );
  }

  /// Starts a server for the specified repo path and port.
  ///
  /// Use port 0 to have the server choose a port. The acutal port used
  /// will be avialalbe in the [serverPort] property after this method
  /// returns. The stdout and stderr of the server will be printed to [stdout]
  /// and [stderr], respectively.
  Future<void> serveRepo(
    String repo, {
    String address = '',
    int port = 0,
  }) async {
    assert(repo != null);
    assert(port != null);
    final List<String> pmCommand = <String>[
      pmPath,
      'serve',
      '-repo', repo, //
      '-l', '$address:$port',
    ];
    stdout.writeln('Running ${pmCommand.join(' ')}');
    _pmServerProcess = await processManager.start(pmCommand);
    final Completer<void> serverPortCompleter = Completer<void>();
    _pmServerProcess.stdout
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen((String line) {
      if (line.contains('serving $repo at http://')) {
        _serverPort = int.parse(line.substring(line.lastIndexOf(':') + 1));
        serverPortCompleter.complete();
      }
      stdout.writeln(line);
    });
    _pmServerProcess.stderr
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen(stderr.writeln);
    await serverPortCompleter.future;
  }

  /// Closes a running server.
  ///
  /// Calling this before calling [serveRepo] will result in a [StateError].
  Future<OperationResult> close() async {
    if (_pmServerProcess == null) {
      throw StateError('Must call serveRepo before calling close.');
    }
    _pmServerProcess.kill();
    final int exitCode = await _pmServerProcess.exitCode;
    _pmServerProcess = null;
    if (exitCode == 0) {
      return OperationResult.success();
    }
    return OperationResult.error(
        'The "pm" executable exited with non-zero exit code.');
  }
}
