// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// Library for injecting and mocking I/O functionalities.
library io;

import 'dart:async';
import 'dart:io' as dart_io;
import 'dart:mirrors';

import 'package:fxutils/fxutils.dart' as fxutils;
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:process/process.dart';

/// Abstract interface for doing I/O (console output, process creation, etc.).
/// See `Standard` for the production implemention used to run `fx codesize`.
/// When running unit tests, we would provide mock implementations which
/// record I/O activities instead.
abstract class Io {
  static Io get() =>
      Zone.current[#io] ?? (throw Exception('Missing dependency #io'));

  /// The standard program output stream.
  StringSink get out;

  /// The error output stream.
  StringSink get err;

  /// Prints the object to the standard output stream.
  void print(Object object);

  ProcessManager get processManager;

  fxutils.FxEnv get fxEnv;

  fxutils.Fx get fx;

  /// Sets the exit code of the program.
  set exitCode(int code);

  /// Returns the current working directory path.
  String get cwd;

  /// Returns the environment variables;
  Map<String, String> get environment;

  File createTempFile(String name);
}

class Standard implements Io {
  static Map<Object, Object> inject() => {#io: Standard()};

  final FileSystem _fs = LocalFileSystem();

  @override
  StringSink get out => dart_io.stdout;

  @override
  StringSink get err => dart_io.stderr;

  @override
  void print(Object object) {
    dart_io.stdout.writeln(object);
  }

  @override
  ProcessManager get processManager => LocalProcessManager();

  fxutils.FxEnv? _fxEnv;

  @override
  fxutils.FxEnv get fxEnv {
    if (_fxEnv != null) {
      return _fxEnv!;
    }

    final envReader = fxutils.EnvReader(cwd: cwd, environment: environment);
    return _fxEnv = fxutils.FxEnv(envReader: envReader);
  }

  fxutils.Fx? _fx;

  @override
  fxutils.Fx get fx {
    if (_fx != null) {
      return _fx!;
    }

    return _fx = fxutils.Fx(fxEnv: fxEnv);
  }

  @override
  set exitCode(int code) => dart_io.exitCode = code;

  @override
  String get cwd => dart_io.Directory.current.path;

  @override
  Map<String, String> get environment => dart_io.Platform.environment;

  @override
  File createTempFile(String name) =>
      _fs.systemTempDirectory.createTempSync().childFile(name);
}

Future<R> runWithIo<IoType extends Io, R>(Future<R> Function() f) {
  // ignore: avoid_as
  final IoType io = (reflectType(IoType) as ClassMirror)
      .newInstance(Symbol(''), []).reflectee;
  return runZoned(f,
      zoneSpecification: ZoneSpecification(
          print: (Zone self, ZoneDelegate parent, Zone zone, String line) =>
              io.out.writeln(line)),
      zoneValues: {#io: io});
}
