// Copyright 2013 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:file/file.dart';
import 'package:file/local.dart';
import 'package:fuchsia_ctl/fuchsia_ctl.dart';
import 'package:path/path.dart' as path;
import 'package:process/process.dart';
import 'package:uuid/uuid.dart';

/// A wrapper around the Fuchsia SDK `pm` tool.
class PackageServer {
  /// Creates a new package server.
  PackageServer(
    this.pmPath, {
    this.processManager = const LocalProcessManager(),
    this.fileSystem = const LocalFileSystem(),
  })  : assert(pmPath != null),
        assert(processManager != null),
        assert(fileSystem != 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;

  /// The file sytem for the package server.
  final FileSystem fileSystem;

  Process _pmServerProcess;

  /// Path to the port file generated by `pm`.
  String portPath;

  /// 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,
    String portFilePath,
  }) async {
    assert(repo != null);
    assert(port != null);

    final String uuid = const Uuid().v4();
    portPath = portFilePath ??
        path.join(fileSystem.systemTempDirectory.path, '${uuid}_port.txt');
    final List<String> pmCommand = <String>[
      pmPath,
      'serve',
      '-repo',
      repo,
      '-l',
      '$address:$port',
      '-f',
      portPath,
    ];
    stdout.writeln('Running ${pmCommand.join(' ')}');
    _pmServerProcess = await processManager.start(pmCommand);
    await Future<void>.delayed(const Duration(seconds: 5), () async {
      final String portString = await fileSystem.file(portPath).readAsString();
      _serverPort = int.parse(portString);
    });
    _pmServerProcess.stdout
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen(stdout.writeln);
    _pmServerProcess.stderr
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen(stderr.writeln);
  }

  /// 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.');
    }
    await fileSystem.file(portPath).delete();
    _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.');
  }
}
