// 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 'dart:math';

import 'package:path/path.dart' as p;
import 'package:process_runner/process_runner.dart';

import 'environment.dart';
import 'json_utils.dart';
import 'logger.dart';
import 'worker_pool.dart';

/// Artifacts from an exited sub-process.
final class ProcessArtifacts {
  /// Constructs an instance of ProcessArtifacts from raw values.
  ProcessArtifacts(
      this.cwd, this.commandLine, this.exitCode, this.stdout, this.stderr,
      {this.pid});

  /// Constructs an instance of ProcessArtifacts from a ProcessRunnerResult
  /// and the spawning context.
  factory ProcessArtifacts.fromResult(
      Directory cwd, List<String> commandLine, ProcessRunnerResult result) {
    return ProcessArtifacts(
        cwd, commandLine, result.exitCode, result.stdout, result.stderr,
        pid: result.pid);
  }

  /// Constructs an instance of ProcessArtifacts from serialized JSON text.
  factory ProcessArtifacts.fromJson(String serialized) {
    final Map<String, dynamic> artifact =
        jsonDecode(serialized) as Map<String, dynamic>;
    final List<String> errors = <String>[];
    final Directory cwd = Directory(stringOfJson(artifact, 'cwd', errors)!);
    final List<String> commandLine =
        stringListOfJson(artifact, 'commandLine', errors)!;
    final int exitCode = intOfJson(artifact, 'exitCode', errors)!;
    final String stdout = stringOfJson(artifact, 'stdout', errors)!;
    final String stderr = stringOfJson(artifact, 'stderr', errors)!;
    final int? pid = intOfJson(artifact, 'pid', errors);
    return ProcessArtifacts(cwd, commandLine, exitCode, stdout, stderr,
        pid: pid);
  }

  /// Constructs an instance of ProcessArtifacts from a file containing JSON.
  factory ProcessArtifacts.fromFile(File file) {
    return ProcessArtifacts.fromJson(file.readAsStringSync());
  }

  /// Saves ProcessArtifacts into file.
  void save(File file) {
    final Map<String, Object> data = <String, Object>{};
    if (pid != null) {
      data['pid'] = pid!;
    }
    data['exitCode'] = exitCode;
    data['stdout'] = stdout;
    data['stderr'] = stderr;
    data['cwd'] = cwd.absolute.path;
    data['commandLine'] = commandLine;
    file.writeAsStringSync(jsonEncodePretty(data));
  }

  /// Creates a temporary file and saves the artifacts into it.
  /// Returns the File.
  File saveTemp() {
    final Directory systemTemp = Directory.systemTemp;
    final String prefix = pid != null ? 'et$pid' : 'et';
    final Directory artifacts = systemTemp.createTempSync(prefix);
    final File resultFile =
        File(p.join(artifacts.path, 'process_artifacts.json'));
    save(resultFile);
    return resultFile;
  }

  /// Current working directory of process when it was spawned.
  final Directory cwd;

  /// Full command line of process.
  final List<String> commandLine;

  /// Exit code.
  final int exitCode;

  /// Stdout (may be empty).
  final String stdout;

  /// Stdout (may be empty).
  final String stderr;

  /// Pid (when available).
  final int? pid;
}

/// A WorkerTask that runs a process
class ProcessTask extends WorkerTask {
  /// Construct a new process task with name, cwd, and command line.
  ProcessTask(super.name, this._environment, this._cwd, this._commandLine);

  final Environment _environment;
  final Directory _cwd;
  final List<String> _commandLine;
  late ProcessArtifacts? _processArtifacts;
  late String? _processArtifactsPath;

  @override
  Future<bool> run() async {
    final ProcessRunnerResult result = await _environment.processRunner
        .runProcess(_commandLine, failOk: true, workingDirectory: _cwd);
    _processArtifacts = ProcessArtifacts(
        _cwd, _commandLine, result.exitCode, result.stdout, result.stderr,
        pid: result.pid);
    _processArtifactsPath = _processArtifacts!.saveTemp().path;
    return result.exitCode == 0;
  }

  /// Returns the ProcessArtifacts after run completes.
  ProcessArtifacts get processArtifacts {
    return _processArtifacts!;
  }

  /// Returns the path that the process artifacts were saved in.
  String get processArtifactsPath {
    return _processArtifactsPath!;
  }
}

/// A WorkerPoolProgressReporter designed to work with ProcessTasks.
class ProcessTaskProgressReporter implements WorkerPoolProgressReporter {
  /// Construct a new reporter.
  ProcessTaskProgressReporter(this._environment);

  final Environment _environment;
  Spinner? _spinner;
  bool _finished = false;
  int _longestName = 0;
  int _doneCount = 0;
  int _totalCount = 0;

  @override
  void onRun(Set<WorkerTask> tasks) {
    _totalCount = tasks.length;
    for (final WorkerTask task in tasks) {
      assert(task is ProcessTask);
      _longestName = max(_longestName, task.name.length);
    }
  }

  @override
  void onFinish() {
    _finished = true;
    _updateSpinner(<ProcessTask>{});
  }

  @override
  void onTaskStart(WorkerPool pool, WorkerTask task) {
    _updateSpinner(pool.running);
  }

  @override
  void onTaskDone(WorkerPool pool, WorkerTask task, [Object? err]) {
    _doneCount++;
    task as ProcessTask;
    final ProcessArtifacts pa = task.processArtifacts;
    final String dt = _formatDurationShort(task.runTime);
    if (pa.exitCode != 0) {
      final String paPath = task.processArtifactsPath;
      _environment.logger.clearLine();
      _environment.logger.status('FAIL: $dt ${task.name} [details in $paPath]');
    } else {
      _environment.logger.clearLine();
      _environment.logger.status('OKAY: $dt ${task.name}');
    }
    _updateSpinner(pool.running);
  }

  void _updateSpinner(Set<WorkerTask> tasks) {
    if (_spinner != null) {
      _spinner!.finish();
      _spinner = null;
    }
    if (_finished) {
      return;
    }
    _environment.logger.clearLine();
    final String taskName = tasks.isEmpty ? '' : tasks.first.name;
    final String etc = tasks.length > 1 ? '... [${tasks.length}]' : '';
    _environment.logger.status(
        'Running $_doneCount/$_totalCount $taskName$etc ',
        newline: false);
    _spinner = _environment.logger.startSpinner();
  }

  String _formatDurationShort(Duration dur) {
    int micros = dur.inMicroseconds;
    String r = '';
    if (micros >= Duration.microsecondsPerMinute) {
      final int minutes = micros ~/ Duration.microsecondsPerMinute;
      micros -= minutes * Duration.microsecondsPerMinute;
      r += '${minutes}m';
    }
    if (micros >= Duration.microsecondsPerSecond) {
      final int seconds = micros ~/ Duration.microsecondsPerSecond;
      micros -= seconds * Duration.microsecondsPerSecond;
      if (r.isNotEmpty) {
        r += '.';
      }
      r += '${seconds}s';
    }
    if (micros >= Duration.microsecondsPerMillisecond) {
      final int millis = micros ~/ Duration.microsecondsPerMillisecond;
      micros -= millis * Duration.microsecondsPerMillisecond;
      if (r.isNotEmpty) {
        r += '.';
      }
      r += '${millis}ms';
    }
    return r.padLeft(15);
  }
}

/// If result.exitCode != 0, will call logger.fatal with relevant information
/// and terminate the program.
void fatalIfFailed(Environment environment, List<String> commandLine,
    ProcessRunnerResult result) {
  if (result.exitCode == 0) {
    return;
  }
  environment.logger.fatal(
      'Process "${commandLine.join(' ')}" failed exitCode=${result.exitCode}\n'
      'STDOUT:\n${result.stdout}'
      'STDERR:\n${result.stderr}');
}

/// Ensures that pathToBinary includes a '.exe' suffix on relevant platforms.
String exePath(Environment environment, String pathToBinary) {
  String suffix = '';
  if (environment.platform.isWindows) {
    suffix = '.exe';
  }
  return '$pathToBinary$suffix';
}

/// Returns the path to the gn binary.
String gnBinPath(Environment environment) {
  return exePath(
      environment,
      p.join(environment.engine.srcDir.path, 'flutter', 'third_party', 'gn',
          'gn'));
}
