// Copyright 2017 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.

import 'dart:async';
import 'dart:collection';
import 'dart:io';

import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:dart_style/dart_style.dart';
import 'package:mustache/mustache.dart';
import 'package:path/path.dart' as path;
import 'package:strings/strings.dart' as strings;
// ignore: implementation_imports
import 'package:widget_explorer_core/src/utils.dart';
import 'package:widget_explorer_core/widget_specs.dart';

final DartFormatter _formatter = new DartFormatter();

Future<Null> main(List<String> args) async {
  String fuchsiaRoot = findFuchsiaRoot();

  String error = checkArgs(args, fuchsiaRoot);
  if (error != null) {
    stderr.writeln(error);
    stdout.writeln('Usage: pub run widget_explorer_gen.dart '
        '<output_dir> <widgets_package_dir> [<widgets_package_dir> ...]');
    exit(1);
  }

  String outputDir = args[0];
  List<String> packageDirs = args.sublist(1);

  List<WidgetSpecs> allWidgetSpecs = packageDirs
      .expand((String packageDir) =>
          extractWidgetSpecs(packageDir, fuchsiaRoot: fuchsiaRoot))
      .toList()
        ..sort();

  await writeIndex(outputDir, allWidgetSpecs);
  await Future.forEach(
    allWidgetSpecs,
    (WidgetSpecs specs) => writeWidgetSpecs(outputDir, specs),
  );
}

/// Try finding the fuchsia root from the current directory.
///
/// Walk up the directories until finding the .jiri_root directory. Returns null
/// if it fails to find the fuchsia root.
String findFuchsiaRoot() {
  Directory current = Directory.current;
  // ignore: literal_only_boolean_expressions
  while (true) {
    FileSystemEntity jiriRoot = current.listSync().firstWhere(
          (FileSystemEntity entity) =>
              path.basename(entity.path) == '.jiri_root' && entity is Directory,
          orElse: () => null,
        );

    if (jiriRoot != null) {
      return current.absolute.path;
    }

    // Break out if we reach the system root directory.
    Directory parent = current.parent;
    if (parent == current) {
      break;
    }

    current = parent;
  }

  return null;
}

/// Check if the provided arguments are valid.
///
/// Returns the reason when there is an error; returns null otherwise.
String checkArgs(List<String> args, String fuchsiaRoot) {
  if (args.length < 2) {
    return 'Invalid number of arguments.';
  }

  String outputDir = args[0];
  if (!new Directory(outputDir).existsSync()) {
    // Try creating the directory.
    try {
      new Directory(outputDir).createSync(recursive: true);
    } on Exception {
      return 'Could not create the output directory "$outputDir".';
    }
  }

  for (int i = 1; i < args.length; ++i) {
    String packageDir = args[i];
    if (!new Directory(packageDir).existsSync()) {
      return 'The specified package directory "$packageDir" does not exist.';
    }

    if (!new File(path.join(packageDir, 'pubspec.yaml')).existsSync()) {
      return 'The specified package directory "$packageDir" '
          'does not contain "pubspec.yaml" file.';
    }

    if (fuchsiaRoot != null) {
      // The fuchsia root dir should be an ancestor of the given package dir.
      if (!path.isWithin(fuchsiaRoot, packageDir)) {
        return 'The fuchsia root should be an ancestor of the package dir.';
      }
    }
  }

  return null;
}

const String _kHeader = '''
// Copyright 2017 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.

// THIS IS A GENERATED FILE. DO NOT MODIFY MANUALLY.''';

const String _kIndexFileTemplate = '''
{{ header }}

import 'package:widget_explorer_core/widget_specs.dart';
import 'package:widget_explorer_widgets/widget_explorer_widgets.dart';

{{ imports }}

/// Map of widget specs.
final Map<String, WidgetSpecs> kWidgetSpecs = <String, WidgetSpecs>{
{{ items }}
};

/// Map of generated widget state builders.
final Map<String, GeneratedStateBuilder> kStateBuilders = <String, GeneratedStateBuilder>{
{{ builders }}
};
''';

/// Writes the index file to the given output directory.
Future<Null> writeIndex(String outputDir, List<WidgetSpecs> widgetSpecs) async {
  String outputPath = path.join(outputDir, 'index.dart');

  Template template = new Template(
    _kIndexFileTemplate,
    htmlEscapeValues: false,
  );

  String imports = widgetSpecs.map((WidgetSpecs specs) {
    String underscoredName = strings.underscore(specs.name);
    return "import '$underscoredName.dart' as $underscoredName;";
  }).join('\n');

  String items = widgetSpecs.map((WidgetSpecs specs) {
    String underscoredName = strings.underscore(specs.name);
    return '  $underscoredName.kName: $underscoredName.kSpecs,';
  }).join('\n');

  String builders = widgetSpecs.map((WidgetSpecs specs) {
    String underscoredName = strings.underscore(specs.name);
    return '  $underscoredName.kName: $underscoredName.kBuilder,';
  }).join('\n');

  String output = template.renderString(<String, dynamic>{
    'header': _kHeader,
    'imports': imports,
    'items': items,
    'builders': builders,
  });

  await new File(outputPath).writeAsString(_formatter.format(output));
}

const String _kSpecFileTemplate = '''
{{ header }}

import 'package:flutter/material.dart';
import 'package:widget_explorer_core/widget_specs.dart';
import 'package:widget_explorer_widgets/widget_explorer_widgets.dart';
import 'package:{{ package_name }}/{{ path }}';

{{# additional_imports }}
import '{{ additional_import }}' as {{ import_id }};
{{/ additional_imports }}

/// Name of the widget.
const String kName = '{{ name }}';

/// [WidgetSpecs] of this widget.
final WidgetSpecs kSpecs = new WidgetSpecs(
  packageName: '{{ package_name }}',
  name: '{{ name }}',
  path: '{{ path }}',
  {{# path_from_fuchsia_root }}
  pathFromFuchsiaRoot: '{{ path_from_fuchsia_root }}',
  {{/ path_from_fuchsia_root }}
  doc: \'\'\'
{{ doc }}\'\'\',
  exampleWidth: {{ example_width }},
  exampleHeight: {{ example_height }},
  hasSizeParam: {{ has_size_param }},
);

/// Generated state object for this widget.
class _Generated{{ name }}State extends GeneratedState {
  {{# params }}
  {{ qualified_param_type }} {{ param_name }};
  {{/ params }}
  {{# generators }}
  {{ generator_declaration }};
  {{/ generators }}

  _Generated{{ name }}State(SetStateFunc setState) : super(setState);

  @override
  void initState(Map<String, dynamic> config) {
    {{# params }}
    {{ param_name }} = {{ param_initial_value }};
    {{/ params }}
  }

  @override
  Widget buildWidget(
    BuildContext context,
    Key key,
    double width,
    double height,
  ) {
    return new {{ name }}(
      key: key,
      {{# params }}
      {{ param_name }}: {{ param_expr }},
      {{/ params }}
    );
  }

  @override
  List<TableRow> buildParameterTableRows(BuildContext context) {
    return <TableRow>[
      {{# params }}
      buildTableRow(
        context,
        <Widget>[
          new Text('{{ param_type }}'),
          new Text('{{ param_name }}'),
          {{ param_controller }},
        ],
      ),
      {{/ params }}
    ];
  }
}

/// State builder for this widget.
final GeneratedStateBuilder kBuilder = (SetStateFunc setState) =>
    new _Generated{{ name }}State(setState);
''';

/// Writes the widget specs to the given output directory.
Future<Null> writeWidgetSpecs(String outputDir, WidgetSpecs specs) async {
  String underscoredName = strings.underscore(specs.name);
  String outputPath = path.join(outputDir, '$underscoredName.dart');

  Template template = new Template(
    _kSpecFileTemplate,
    htmlEscapeValues: false,
  );

  // Escape single quotes within the doc comments.
  String escapedDoc = _escapeQuotes(specs.doc);

  Set<String> additionalImports = new SplayTreeSet<String>();
  Map<String, String> importIdMap = <String, String>{};
  Set<DartType> generators = new SplayTreeSet<DartType>(
    (DartType t1, DartType t2) => t1.name.compareTo(t2.name),
  );
  List<ParameterElement> params = <ParameterElement>[];

  ConstructorElement constructor = specs.classElement.constructors.firstWhere(
      (ConstructorElement c) => c.isDefaultConstructor,
      orElse: () => null);

  if (constructor != null) {
    params = new List<ParameterElement>.from(constructor.parameters)
      ..removeWhere((ParameterElement param) => param.type.name == 'Key')
      ..forEach((ParameterElement param) =>
          _addImportForType(additionalImports, importIdMap, param.type));
  }

  // The parameter controllers / initial values should be generated here first
  // so that the additional imports can be safely added.
  List<Map<String, String>> paramList = params
      .map((ParameterElement param) => <String, String>{
            'qualified_param_type':
                _getQualifiedTypeName(importIdMap, param.type),
            'param_type': _getTypeName(param.type),
            'param_name': param.name,
            'param_controller': _generateParamControllerCode(
              additionalImports,
              importIdMap,
              generators,
              specs,
              param,
            ),
            'param_initial_value': _generateInitialValueCode(
              additionalImports,
              importIdMap,
              generators,
              specs,
              param,
            ),
            'param_expr': _generateParameterExpression(param),
          })
      .toList();

  List<Map<String, String>> generatorList = generators
      .map((DartType generatorType) => <String, String>{
            'generator_declaration':
                '${_getImportIdPrefixForType(importIdMap, generatorType)}'
                '${generatorType.name} '
                '${lowerCamelize(generatorType.name)} = '
                'new ${_getImportIdPrefixForType(importIdMap, generatorType)}'
                '${generatorType.name}()',
          })
      .toList();

  String output = template.renderString(<String, dynamic>{
    'header': _kHeader,
    'package_name': specs.packageName,
    'name': specs.name,
    'path': specs.path,
    'path_from_fuchsia_root': specs.pathFromFuchsiaRoot != null
        ? <String, String>{'path_from_fuchsia_root': specs.pathFromFuchsiaRoot}
        : null,
    'doc': escapedDoc,
    'example_width': _doubleValueToCode(specs.exampleWidth),
    'example_height': _doubleValueToCode(specs.exampleHeight),
    'has_size_param': specs.hasSizeParam,
    'additional_imports': additionalImports
        .map((String uri) => <String, String>{
              'additional_import': uri,
              'import_id': importIdMap[uri],
            })
        .toList(),
    'params': paramList,
    'generators': generatorList,
  });

  await new File(outputPath).writeAsString(_formatter.format(output));
}

String _generateParamControllerCode(
  Set<String> additionalImports,
  Map<String, String> importIdMap,
  Set<DartType> generators,
  WidgetSpecs specs,
  ParameterElement param,
) {
  // TODO(youngseokyoon): handle more types of values.

  // Handle size parameters.
  if (_isWidthParam(param)) {
    return "new InfoText('width value is used')";
  }

  if (_isHeightParam(param)) {
    return "new InfoText('height value is used')";
  }

  if (_isSizeParam(param)) {
    return "new InfoText('size value is used')";
  }

  // For int type, use a TextField where the user can type in the integer value.
  if (param.type.name == 'int') {
    return '''new TextFieldWithInitialValue(
      initialValue: (${param.name} ?? 0).toString(),
      keyboardType: TextInputType.number,
      onChanged: (String value) {
        try {
          int intValue = int.parse(value);
          setState(() {
            ${param.name} = intValue;
          });
        } catch (e) {
          // Do nothing.
        }
      },
    )''';
  }

  // For bool type, use a Switch widget.
  // Since we don't want the Switch widget to take up the entire width, add an
  // empty widget next to it.
  if (param.type.name == 'bool') {
    return '''new Row(
      children: <Widget>[
        new Switch(
          value: ${param.name} ?? false,
          onChanged: (bool value) {
            setState(() {
              ${param.name} = value;
            });
          },
        ),
        new Expanded(child: new Container()),
      ],
    )''';
  }

  // For double type, use a TextField where the user can type the value.
  if (param.type.name == 'double') {
    return '''new TextFieldWithInitialValue(
        initialValue: (${param.name} ?? 0.0).toString(),
        keyboardType: TextInputType.number,
        onChanged: (String value) {
          try {
            double doubleValue = double.parse(value);
            setState(() {
              ${param.name} = doubleValue;
            });
          } catch (e) {
            // Do nothing.
          }
        },
      )''';
  }

  // For String type, use a TextField where the user can type in the value.
  if (param.type.name == 'String') {
    // If this parameter should be retrieved from the config.json file, do not
    // show the values on the screen.
    String configKey = specs.getConfigKey(param);
    if (configKey != null) {
      return """new ConfigKeyText(
        configKey: '${_escapeQuotes(configKey)}',
        configValue: ${param.name},
      )""";
    }

    return '''new TextFieldWithInitialValue(
      initialValue: ${param.name},
      onChanged: (String value) {
        setState(() {
          ${param.name} = value;
        });
      },
    )''';
  }

  // Handle enum parameters with a popup menu button.
  if (_isEnumParameter(param)) {
    return '''new PopupMenuButton<${_getQualifiedTypeName(importIdMap, param.type)}>(
      itemBuilder: (BuildContext context) {
        return ${_getQualifiedTypeName(importIdMap, param.type)}.values.map((${_getQualifiedTypeName(importIdMap, param.type)} value) {
          return new PopupMenuItem<${_getQualifiedTypeName(importIdMap, param.type)}>(
            value: value,
            child: new Text(value.toString()),
          );
        }).toList();
      },
      initialValue: ${_getQualifiedTypeName(importIdMap, param.type)}.values[0],
      onSelected: (${_getQualifiedTypeName(importIdMap, param.type)} value) {
        setState(() {
          ${param.name} = value;
        });
      },
      child: new Text((${param.name} ?? 'null').toString()),
    )''';
  }

  // Handle callback parameters.
  if (_isCallbackParameter(param)) {
    return "new InfoText('Default implementation')";
  }

  // Handle parameters with a specified generator.
  ElementAnnotation generatorAnnotation = _getGenerator(param);
  if (generatorAnnotation != null) {
    DartObject generatorObj = generatorAnnotation.computeConstantValue();
    DartType generatorType = generatorObj.getField('type').toTypeValue();
    String methodName = generatorObj.getField('methodName').toStringValue();

    // Add the generator type to the list of additional imports and generators.
    _addImportForType(additionalImports, importIdMap, generatorType);
    generators.add(generatorType);

    // The actual code to invoke (e.g. `modelFixtures.thread()`).
    String generatorInvocationCode =
        _getGeneratorInvocationCode(generatorType, methodName);

    // Place a button widget for regenerating the value.
    return '''new RegenerateButton(
      onPressed: () {
        setState(() {
          ${param.name} = $generatorInvocationCode;
        });
      },
      codeToDisplay: '${_escapeQuotes(generatorInvocationCode)}',
    )''';
  }

  return "new InfoText('null (this type of parameter is not supported yet)')";
}

String _generateInitialValueCode(
  Set<String> additionalImports,
  Map<String, String> importIdMap,
  Set<DartType> generators,
  WidgetSpecs specs,
  ParameterElement param,
) {
  // See if there is an example value specified.
  dynamic value = specs.getExampleValue(param);
  if (value != null) {
    switch (value.runtimeType) {
      case int:
      case bool:
      case double:
        return value.toString();
      case String:
        return "'''${_escapeQuotes(value.toString())}'''";
      default:
        return 'null';
    }
  }

  // Retrieve the config value associated with the specified config key.
  String configKey = specs.getConfigKey(param);
  if (configKey != null) {
    return "config['${_escapeQuotes(configKey)}']";
  }

  // TODO(youngseokyoon): See if the parameter type has a default constructor
  // that can be used.
  // if (param.type.element is ClassElement) {
  //   ClassElement type = param.type.element;
  //   if (type.constructors
  //       .any((ConstructorElement c) => c.isDefaultConstructor)) {
  //     return 'new ${param.type.name}()';
  //   }
  // }

  // Handle primitive types.
  switch (param.type.name) {
    case 'int':
      return '0';
    case 'bool':
      return 'false';
    case 'double':
      return '0.0';
    case 'String':
      return "''";
  }

  // Handle enum types.
  if (_isEnumParameter(param)) {
    return '${_getQualifiedTypeName(importIdMap, param.type)}.values[0]';
  }

  // Handle callback parameters.
  if (_isCallbackParameter(param)) {
    FunctionTypedElement func = param.type.element;
    String functionName = '${specs.name}.${param.name}';

    // Print out all the parameter values to the console.
    if (func.parameters.isNotEmpty) {
      String paramList = func.parameters
          .map((ParameterElement p) => 'dynamic ${p.name}')
          .join(', ');
      String valueList =
          func.parameters.map((ParameterElement p) => p.name).join(', ');
      return "($paramList) => print('$functionName called "
          "with parameters: \${<dynamic>[$valueList]}')";
    }

    // If the callback function has no parameters, just say it was called.
    return "() => print('$functionName called')";
  }

  // Handle parameters with a specified generator.
  ElementAnnotation generatorAnnotation = _getGenerator(param);
  if (generatorAnnotation != null) {
    DartObject generatorObj = generatorAnnotation.computeConstantValue();
    DartType generatorType = generatorObj.getField('type').toTypeValue();
    String methodName = generatorObj.getField('methodName').toStringValue();

    // Place a button widget for regenerating the value.
    return _getGeneratorInvocationCode(generatorType, methodName);
  }

  // Otherwise, return 'null';
  return 'null';
}

String _generateParameterExpression(ParameterElement param) {
  if (_isWidthParam(param)) {
    return 'width';
  }

  if (_isHeightParam(param)) {
    return 'height';
  }

  if (_isSizeParam(param)) {
    // In this case, the width and height value must be the same, and it doesn't
    // matter which one we use. Just using the width value here.
    return 'width';
  }

  return 'this.${param.name}';
}

/// Returns the display name of the given type.
///
/// If the type has generic type arguments, returns 'dynamic' instead, to avoid
/// having to deal with analyzer errors for now.
String _getTypeName(DartType type) {
  // TODO(youngseokyoon): Handle generic type arguments correctly.
  // https://fuchsia.atlassian.net/browse/SO-259
  if (type is ParameterizedType) {
    ParameterizedType parameterizedType = type;
    if (parameterizedType.typeArguments?.isNotEmpty ?? false) {
      return 'dynamic';
    }
  }

  return type.name;
}

/// Determines whether the provided parameter is of an enum type.
bool _isEnumParameter(ParameterElement param) {
  if (param?.type?.element is! ClassElement) {
    return false;
  }

  ClassElement paramType = param.type.element;
  return paramType.isEnum;
}

/// Determines whether the provided parameter represents a callback function.
///
/// We consider any function parameter with a void return type as a callback.
bool _isCallbackParameter(ParameterElement param) {
  if (param?.type?.element is! FunctionTypedElement) {
    return false;
  }

  FunctionTypedElement func = param.type.element;
  return func.returnType.isVoid;
}

/// Gets the @Generator annotation of the given parameter.
ElementAnnotation _getGenerator(ParameterElement param) {
  ElementAnnotation annotation;

  // An @Generator annotation on the parameter itself has a higher priority.
  annotation = getAnnotationWithName(param, 'Generator');
  if (annotation != null) {
    return annotation;
  }

  // Also see if the parameter type (class) has an @Generator annotation.
  return annotation = getAnnotationWithName(param?.type?.element, 'Generator');
}

/// Gets the code for invoking the generator.
String _getGeneratorInvocationCode(DartType generatorType, String methodName) {
  return '${lowerCamelize(generatorType.name)}.$methodName()';
}

bool _isWidthParam(ParameterElement param) {
  return getAnnotationWithName(param, '_WidthParam') != null;
}

bool _isHeightParam(ParameterElement param) {
  return getAnnotationWithName(param, '_HeightParam') != null;
}

bool _isSizeParam(ParameterElement param) {
  return getAnnotationWithName(param, '_SizeParam') != null;
}

/// Escape all single quotes in the given string with a leading backslash,
/// except for the ones already escaped.
String _escapeQuotes(String str) {
  return str?.replaceAllMapped(
    new RegExp(r"([^\\])'"),
    (Match m) => "${m.group(1)}\\\'",
  );
}

void _addImportForType(
  Set<String> additionalImports,
  Map<String, String> importIdMap,
  DartType type,
) {
  Uri importUri = type?.element?.librarySource?.uri;
  String importUriString = importUri?.toString();
  if (importUriString != null &&
      importUriString != 'dart:core' &&
      !additionalImports.contains(importUriString)) {
    additionalImports.add(importUriString);
    // Specify an identifier (i.e. import '..' as foo) to avoid name collision.
    String idBase = strings.underscore(
      path.basenameWithoutExtension(importUri.pathSegments.last),
    );
    String id = idBase;

    // Here, just in case the import id name is already in use, add a number at
    // the end of the id name by increasing the number until it doesn't collide
    // with an existing id.
    int count = 1;
    while (importIdMap.values.contains(id)) {
      ++count;
      id = '$idBase$count';
    }
    importIdMap[importUriString] = id;
  }
}

/// Returns the import identifier prefix for the given type.
///
/// For example, if "foo.dart" was imported as "foo",
///     import 'foo.dart' as foo;
///
/// and the `Foo` type was given as the second parameter, this function returns
/// `'foo.'` with the trailing dot.
///
/// Otherwise, this function returns empty string.
String _getImportIdPrefixForType(
  Map<String, String> importIdMap,
  DartType type,
) {
  String importUriString = type?.element?.librarySource?.uri?.toString();
  String importId = importIdMap[importUriString];
  return importId != null ? '$importId.' : '';
}

/// Returns the fully qualified name for the given type.
String _getQualifiedTypeName(
  Map<String, String> importIdMap,
  DartType type,
) {
  String typeName = _getTypeName(type);
  String prefix =
      typeName == 'dynamic' ? '' : _getImportIdPrefixForType(importIdMap, type);
  return '$prefix$typeName';
}

String _doubleValueToCode(double value) {
  if (value == double.nan) {
    return 'double.NAN';
  } else if (value == double.infinity) {
    return 'double.INFINITY';
  } else if (value == double.negativeInfinity) {
    return 'double.NEGATIVE_INFINITY';
  } else if (value == double.minPositive) {
    return 'double.MIN_POSITIVE';
  } else if (value == double.maxFinite) {
    return 'double.MAX_FINITE';
  } else if (value == null) {
    return 'null';
  }

  return value.toString();
}
