// Copyright (c) 2020, 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' as io;

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

import '../core.dart';
import '../progress.dart';
import '../sdk.dart';
import '../templates.dart';
import '../utils.dart';

/// A command to create a new project from a set of templates.
class CreateCommand extends DartdevCommand {
  static const String cmdName = 'create';

  static const String defaultTemplateId = 'console';

  static List<String> legalTemplateIds({bool includeDeprecated = false}) => [
    for (var g in generators) ...[
      if (includeDeprecated || !g.deprecated) g.id,
      if (includeDeprecated && g.alternateId != null) g.alternateId!,
    ],
  ];

  static final Map<String, String> templateHelp = {
    for (var g in generators)
      if (!g.deprecated) g.id: g.description,
  };

  CreateCommand({bool verbose = false})
    : super(cmdName, 'Create a new Dart project.', verbose) {
    argParser.addOption(
      'template',
      allowed: legalTemplateIds(includeDeprecated: true),
      allowedHelp: templateHelp,
      help: 'The project template to use.',
      defaultsTo: defaultTemplateId,
      abbr: 't',
    );
    argParser.addFlag(
      'pub',
      defaultsTo: true,
      help: "Whether to run 'pub get' after the project has been created.",
    );
    argParser.addFlag(
      'list-templates',
      negatable: false,
      hide: !verbose,
      help: 'List the available templates in JSON format.',
    );
    argParser.addFlag(
      'force',
      negatable: false,
      help:
          'Force project generation, even if the target directory already '
          'exists.',
    );
  }

  @override
  String get invocation => '${super.invocation} <directory>';

  @override
  CommandCategory get commandCategory => CommandCategory.project;

  @override
  FutureOr<int> run() async {
    final args = argResults!;
    if (args.flag('list-templates')) {
      log.stdout(_availableTemplatesJson());
      return 0;
    }

    if (args.rest.isEmpty) {
      printUsage();
      return 1;
    }

    String templateId = args.option('template')!;

    String dir = args.rest.first;
    var targetDir = io.Directory(dir).absolute;
    dir = targetDir.path;
    if (targetDir.existsSync() && !args.flag('force')) {
      log.stderr(
        "Directory '$dir' already exists "
        "(use '--force' to force project generation).",
      );
      return 73;
    }

    String projectName = p.basename(dir);
    if (projectName == '.') {
      projectName = p.basename(io.Directory.current.path);
    }
    projectName = normalizeProjectName(projectName);

    if (!isValidPackageName(projectName)) {
      log.stderr(
        '"$projectName" is not a valid Dart project name.\n\n'
        'See https://dart.dev/tools/pub/pubspec#name for more information.',
      );
      return 73;
    }

    log.stdout(
      'Creating ${log.ansi.emphasized(projectName)} '
      'using template $templateId...',
    );
    log.stdout('');

    var generator = getGenerator(templateId)!;
    generator.generate(
      projectName,
      DirectoryGeneratorTarget(generator, io.Directory(dir)),
    );

    if (args.flag('pub')) {
      log.stdout('');

      // Run 'pub get'. We display output from the pub command, but keep the
      // output terse. This is to give the user a sense of the work that pub
      // did without scrolling the previous stdout sections off the screen.
      final buffer = StringBuffer();
      final exitCode = await progress(
        'Running pub get',
        () => runProcess(
          [sdk.dart, 'pub', 'get'],
          cwd: dir,
          logToTrace: true,
          listener: (str) {
            // Filter lines like '+ multi_server_socket 1.0.2'.
            if (!str.startsWith('+ ')) {
              buffer.writeln('  $str');
            }
          },
        ),
      );
      log.stdout(buffer.toString().trimRight());
      if (exitCode != 0) return exitCode;
    }

    log.stdout('');
    log.stdout(
      'Created project $projectName in ${p.relative(dir)}! In order to get '
      'started, run the following commands:',
    );
    log.stdout('');
    log.stdout(generator.getInstallInstructions(dir, scriptPath: projectName));
    log.stdout('');

    return 0;
  }

  String _availableTemplatesJson() {
    var items = generators.where((g) => !g.deprecated).map((
      Generator generator,
    ) {
      var m = {
        'name': generator.id,
        'label': generator.label,
        'description': generator.description,
        'categories': generator.categories,
      };

      if (generator.entrypoint != null) {
        m['entrypoint'] = generator.entrypoint!.path;
      }

      return m;
    });

    JsonEncoder encoder = const JsonEncoder.withIndent('  ');
    return encoder.convert(items.toList());
  }
}

class DirectoryGeneratorTarget extends GeneratorTarget {
  final Generator generator;
  final io.Directory dir;

  DirectoryGeneratorTarget(this.generator, this.dir) {
    if (!dir.existsSync()) {
      dir.createSync();
    }
  }

  @override
  void createFile(String path, List<int> contents) {
    io.File file = io.File(p.join(dir.path, path));

    String name = p.relative(file.path, from: dir.path);
    log.stdout('  $name');

    file.createSync(recursive: true);
    file.writeAsBytesSync(contents);
  }
}
