// Copyright (c) 2018, 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 'package:dart_style/dart_style.dart';

import 'typescript.dart';

final formatter = new DartFormatter();
Map<String, Interface> _interfaces = {};
Map<String, Namespace> _namespaces = {};
Map<String, TypeAlias> _typeAliases = {};

String generateDartForTypes(List<ApiItem> types) {
  // Keep maps of items we may need to look up quickly later.
  types
      .whereType<TypeAlias>()
      .forEach((alias) => _typeAliases[alias.name] = alias);
  types
      .whereType<Interface>()
      .forEach((interface) => _interfaces[interface.name] = interface);
  types
      .whereType<Namespace>()
      .forEach((namespace) => _namespaces[namespace.name] = namespace);
  final buffer = new IndentableStringBuffer();
  _getSorted(types).forEach((t) => _writeType(buffer, t));
  final formattedCode = _formatCode(buffer.toString());
  return formattedCode.trim() + '\n'; // Ensure a single trailing newline.
}

String _formatCode(String code) {
  try {
    code = formatter.format(code);
  } catch (e) {
    print('Failed to format code, returning unformatted code.');
  }
  return code;
}

/// Recursively gets all members from superclasses.
List<Field> _getAllFields(Interface interface) {
  // Handle missing interfaces (such as special cased interfaces that won't
  // be included in this model).
  if (interface == null) {
    return [];
  }
  return interface.members
      .whereType<Field>()
      .followedBy(interface.baseTypes
          .map((name) => _getAllFields(_interfaces[name]))
          .expand((ts) => ts))
      .toList();
}

String _getListType(String type) {
  return type.substring('List<'.length, type.length - 1);
}

/// Returns a copy of the list sorted by name.
List<ApiItem> _getSorted(List<ApiItem> items) {
  final sortedList = items.toList();
  sortedList.sort((item1, item2) => item1.name.compareTo(item2.name));
  return sortedList;
}

List<String> _getUnionTypes(String type) {
  return type
      .substring('EitherX<'.length, type.length - 1)
      .split(',')
      .map((s) => s.trim())
      .toList();
}

bool _isList(String type) {
  return type.startsWith('List<') && type.endsWith('>');
}

bool _isLiteral(String type) {
  const literals = ['num', 'String', 'bool'];
  return literals.contains(type);
}

bool _isSpecType(String type) {
  return _interfaces.containsKey(type) || _namespaces.containsKey(type);
}

bool _isUnion(String type) {
  return type.startsWith('Either') && type.endsWith('>');
}

/// Maps reserved words and identifiers that cause issues in field names.
String _makeValidIdentifier(String identifier) {
  // The SymbolKind class has uses these names which cause issues for code that
  // uses them as types.
  const map = {
    'Object': 'Obj',
    'String': 'Str',
  };
  return map[identifier] ?? identifier;
}

/// Maps a TypeScript type on to a Dart type, including following TypeAliases.
String _mapType(List<String> types) {
  const mapping = <String, String>{
    'boolean': 'bool',
    'string': 'String',
    'number': 'num',
    'any': 'dynamic',
    // Special cases that are hard to parse or anonymous types.
    '{ [uri: string]: TextEdit[]; }': 'Map<String, List<TextEdit>>',
    '{ language: string; value: string }': 'MarkedStringWithLanguage'
  };
  if (types.length > 4) {
    throw 'Unions of more than 4 types are not supported.';
  }
  if (types.length >= 2) {
    final typeArgs = types.map((t) => _mapType([t])).join(', ');
    return 'Either${types.length}<$typeArgs>';
  }

  final type = types.first;
  if (type.endsWith('[]')) {
    return 'List<${_mapType([type.substring(0, type.length - 2)])}>';
  }
  if (_typeAliases.containsKey(type)) {
    return _mapType([_typeAliases[type].baseType]);
  }
  if (mapping.containsKey(type)) {
    return _mapType([mapping[type]]);
  }
  return type;
}

String _rewriteCommentReference(String comment) {
  final commentReferencePattern = new RegExp(r'\[([\w ]+)\]\(#(\w+)\)');
  return comment.replaceAllMapped(commentReferencePattern, (m) {
    final description = m.group(1);
    final reference = m.group(2);
    if (description == reference) {
      return '[$reference]';
    } else {
      return '$description ([$reference])';
    }
  });
}

Iterable<String> _wrapLines(List<String> lines, int maxLength) sync* {
  lines = lines.map((l) => l.trimRight()).toList();
  for (var line in lines) {
    while (true) {
      if (line.length <= maxLength) {
        yield line;
        break;
      } else {
        int lastSpace = line.lastIndexOf(' ', maxLength);
        // If there was no valid place to wrap, yield the whole string.
        if (lastSpace == -1) {
          yield line;
          break;
        } else {
          yield line.substring(0, lastSpace);
          line = line.substring(lastSpace + 1);
        }
      }
    }
  }
}

void _writeCanParseMethod(IndentableStringBuffer buffer, Interface interface) {
  buffer
    ..writeIndentedln('static bool canParse(Object obj) {')
    ..indent()
    ..writeIndentedln('return obj is Map<String, dynamic>');
  // In order to consider this valid for parsing, all fields that may not be
  // undefined must be present and also type check for the correct type.
  final requiredFields =
      _getAllFields(interface).where((f) => !f.allowsUndefined);
  for (var field in requiredFields) {
    buffer.write("&& obj.containsKey('${field.name}') && ");
    _writeTypeCheckCondition(
        buffer, "obj['${field.name}']", _mapType(field.types));
  }
  buffer
    ..writeln(';')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeConst(IndentableStringBuffer buffer, Const cons) {
  _writeDocCommentsAndAnnotations(buffer, cons);
  buffer.writeIndentedln('static const ${cons.name} = ${cons.value};');
}

void _writeConstructor(IndentableStringBuffer buffer, Interface interface) {
  final allFields = _getAllFields(interface);
  if (allFields.isEmpty) {
    return;
  }
  buffer
    ..writeIndented('${interface.name}(')
    ..write(allFields.map((field) => 'this.${field.name}').join(', '))
    ..write(')');
  final fieldsWithValidation =
      allFields.where((f) => !f.allowsNull && !f.allowsUndefined).toList();
  if (fieldsWithValidation.isNotEmpty) {
    buffer
      ..writeIndentedln(' {')
      ..indent();
    for (var field in fieldsWithValidation) {
      buffer
        ..writeIndentedln('if (${field.name} == null) {')
        ..indent()
        ..writeIndentedln(
            "throw '${field.name} is required but was not provided';")
        ..outdent()
        ..writeIndentedln('}');
    }
    buffer
      ..outdent()
      ..writeIndentedln('}');
  } else {
    buffer.writeln(';');
  }
}

void _writeDocCommentsAndAnnotations(
    IndentableStringBuffer buffer, ApiItem item) {
  var comment = item.comment?.trim();
  if (comment == null || comment.length == 0) {
    return;
  }
  comment = _rewriteCommentReference(comment);
  Iterable<String> lines = comment.split('\n');
  // Wrap at 80 - 4 ('/// ') - indent characters.
  lines = _wrapLines(lines, (80 - 4 - buffer.totalIndent).clamp(0, 80));
  lines.forEach((l) => buffer.writeIndentedln('/// $l'.trim()));
  if (item.isDeprecated) {
    buffer.writeIndentedln('@core.deprecated');
  }
}

void _writeEnumClass(IndentableStringBuffer buffer, Namespace namespace) {
  _writeDocCommentsAndAnnotations(buffer, namespace);
  buffer
    ..writeln('class ${namespace.name} {')
    ..indent()
    ..writeIndentedln('const ${namespace.name}._(this._value);')
    ..writeIndentedln('const ${namespace.name}.fromJson(this._value);')
    ..writeln()
    ..writeIndentedln('final Object _value;')
    ..writeln()
    ..writeIndentedln('static bool canParse(Object obj) {')
    ..indent()
    ..writeIndentedln('switch (obj) {')
    ..indent();
  namespace.members.whereType<Const>().forEach((cons) {
    buffer..writeIndentedln('case ${cons.value}:');
  });
  buffer
    ..indent()
    ..writeIndentedln('return true;')
    ..outdent()
    ..writeIndentedln('}')
    ..writeIndentedln('return false;')
    ..outdent()
    ..writeIndentedln('}');
  namespace.members.whereType<Const>().forEach((cons) {
    _writeDocCommentsAndAnnotations(buffer, cons);
    buffer
      ..writeIndentedln(
          'static const ${_makeValidIdentifier(cons.name)} = const ${namespace.name}._(${cons.value});');
  });
  buffer
    ..writeln()
    ..writeIndentedln('Object toJson() => _value;')
    ..writeln()
    ..writeIndentedln('@override String toString() => _value.toString();')
    ..writeln()
    ..writeIndentedln('@override get hashCode => _value.hashCode;')
    ..writeln()
    ..writeIndentedln(
        'bool operator ==(o) => o is ${namespace.name} && o._value == _value;')
    ..outdent()
    ..writeln('}')
    ..writeln();
}

void _writeField(IndentableStringBuffer buffer, Field field) {
  _writeDocCommentsAndAnnotations(buffer, field);
  buffer
    ..writeIndented('final ')
    ..write(_mapType(field.types))
    ..writeln(' ${field.name};');
}

void _writeFromJsonCode(
    IndentableStringBuffer buffer, List<String> types, String valueCode) {
  final type = _mapType(types);
  if (_isLiteral(type)) {
    buffer.write("$valueCode");
  } else if (_isSpecType(type)) {
    // Our own types have fromJson() constructors we can call.
    buffer.write("new $type.fromJson($valueCode)");
  } else if (_isList(type)) {
    // Lists need to be mapped so we can recursively call (they may need fromJson).
    buffer.write("$valueCode?.map((item) => ");
    final listType = _getListType(type);
    _writeFromJsonCode(buffer, [listType], 'item');
    buffer.write(')?.cast<$listType>()?.toList()');
  } else if (_isUnion(type)) {
    _writeFromJsonCodeForUnion(buffer, types, valueCode);
  } else {
    buffer.write("$valueCode");
  }
}

void _writeFromJsonCodeForUnion(
    IndentableStringBuffer buffer, List<String> types, String valueCode) {
  final unionTypeName = _mapType(types);
  // Write a check against each type, eg.:
  // x is y ? new Either.tx(x) : (...)
  for (var i = 0; i < types.length; i++) {
    final dartType = _mapType([types[i]]);

    _writeTypeCheckCondition(buffer, valueCode, dartType);
    buffer.write(' ? new $unionTypeName.t${i + 1}(');
    _writeFromJsonCode(buffer, [dartType], valueCode); // Call recursively!
    buffer.write(') : (');
  }
  // Fill the final parens with a throw because if we fell through all of the
  // cases then the value we had didn't match any of the types in the union.
  buffer
      .write("throw '''\${$valueCode} was not one of (${types.join(', ')})'''");
  buffer.write(')' * types.length);
}

void _writeFromJsonConstructor(
    IndentableStringBuffer buffer, Interface interface) {
  final allFields = _getAllFields(interface);
  if (allFields.isEmpty) {
    return;
  }
  buffer
    ..writeIndentedln(
        'factory ${interface.name}.fromJson(Map<String, dynamic> json) {')
    ..indent();
  for (final field in allFields) {
    buffer.writeIndented('final ${field.name} = ');
    _writeFromJsonCode(buffer, field.types, "json['${field.name}']");
    buffer.writeln(';');
  }
  buffer
    ..writeIndented('return new ${interface.name}(')
    ..write(allFields.map((field) => '${field.name}').join(', '))
    ..writeln(');')
    ..outdent()
    ..write('}');
}

void _writeInterface(IndentableStringBuffer buffer, Interface interface) {
  _writeDocCommentsAndAnnotations(buffer, interface);

  buffer.writeIndented('class ${interface.name} ');
  if (interface.baseTypes.isNotEmpty) {
    buffer.writeIndented('implements ${interface.baseTypes.join(', ')} ');
  }
  buffer
    ..writeln('{')
    ..indent();
  _writeConstructor(buffer, interface);
  _writeFromJsonConstructor(buffer, interface);
  // Handle Consts and Fields separately, since we need to include superclass
  // Fields.
  final consts = interface.members.whereType<Const>().toList();
  final fields = _getAllFields(interface);
  buffer.writeln();
  _writeMembers(buffer, consts);
  buffer.writeln();
  _writeMembers(buffer, fields);
  buffer.writeln();
  _writeToJsonMethod(buffer, interface);
  _writeCanParseMethod(buffer, interface);
  buffer
    ..outdent()
    ..writeIndentedln('}')
    ..writeln();
}

void _writeJsonMapAssignment(
    IndentableStringBuffer buffer, Field field, String mapName) {
  // If we are allowed to be undefined (which essentially means required to be
  // undefined and never explicitly null), we'll only add the value if set.
  if (field.allowsUndefined) {
    buffer
      ..writeIndentedlnIf(
          field.isDeprecated, '// ignore: deprecated_member_use')
      ..writeIndentedln('if (${field.name} != null) {')
      ..indent();
  }
  buffer
    ..writeIndentedlnIf(field.isDeprecated, '// ignore: deprecated_member_use')
    ..writeIndented('''$mapName['${field.name}'] = ${field.name}''');
  if (!field.allowsUndefined && !field.allowsNull) {
    buffer.write(''' ?? (throw '${field.name} is required but was not set')''');
  }
  buffer.writeln(';');
  if (field.allowsUndefined) {
    buffer
      ..outdent()
      ..writeIndentedln('}');
  }
}

void _writeMember(IndentableStringBuffer buffer, Member member) {
  if (member is Field) {
    _writeField(buffer, member);
  } else if (member is Const) {
    _writeConst(buffer, member);
  } else {
    throw 'Unknown type';
  }
}

void _writeMembers(IndentableStringBuffer buffer, List<Member> members) {
  _getSorted(members).forEach((m) => _writeMember(buffer, m));
}

void _writeNamespace(IndentableStringBuffer buffer, Namespace namespace) {
  // Namespaces are just groups of constants. For some uses we can write these
  // as enum classes for extra type safety, but not for all - for example
  // CodeActionKind can be an arbitrary String even though it also defines
  // constants for common values. We can tell which can have their own values
  // because they're marked with type aliases, with the exception of ErrorCodes!
  if (!_typeAliases.containsKey(namespace.name) &&
      namespace.name != 'ErrorCodes') {
    _writeEnumClass(buffer, namespace);
    return;
  }

  _writeDocCommentsAndAnnotations(buffer, namespace);
  buffer
    ..writeln('abstract class ${namespace.name} {')
    ..indent();
  _writeMembers(buffer, namespace.members);
  buffer
    ..outdent()
    ..writeln('}')
    ..writeln();
}

void _writeToJsonMethod(IndentableStringBuffer buffer, Interface interface) {
  // It's important the name we use for the map here isn't in use in the object
  // already. 'result' was, so we prefix it with some underscores.
  buffer
    ..writeIndentedln('Map<String, dynamic> toJson() {')
    ..indent()
    ..writeIndentedln('Map<String, dynamic> __result = {};');
  for (var field in _getAllFields(interface)) {
    _writeJsonMapAssignment(buffer, field, '__result');
  }
  buffer
    ..writeIndentedln('return __result;')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeType(IndentableStringBuffer buffer, ApiItem type) {
  if (type is Interface) {
    _writeInterface(buffer, type);
  } else if (type is Namespace) {
    _writeNamespace(buffer, type);
  } else if (type is TypeAlias) {
    // For now type aliases are not supported, so are collected at the start
    // of the process in a map, and just replaced with the aliased type during
    // generation.
    // _writeTypeAlias(buffer, type);
  } else {
    throw 'Unknown type';
  }
}

void _writeTypeCheckCondition(
    IndentableStringBuffer buffer, String valueCode, String dartType) {
  if (dartType == 'dynamic') {
    buffer.write('true');
  } else if (_isLiteral(dartType)) {
    buffer.write('$valueCode is $dartType');
  } else if (_isSpecType(dartType)) {
    buffer.write('$dartType.canParse($valueCode)');
  } else if (_isList(dartType)) {
    // TODO(dantup): If we're happy to assume we never have two lists in a union
    // we could simplify this to '$valueCode is List'.
    buffer.write(
        '($valueCode is List && ($valueCode.length == 0 || $valueCode.every((item) => ');
    _writeTypeCheckCondition(buffer, 'item', _getListType(dartType));
    buffer.write(')))');
  } else if (_isUnion(dartType)) {
    // To type check a union, we just recursively check against each of its types.
    final unionTypes = _getUnionTypes(dartType);
    buffer.write('(');
    for (var i = 0; i < unionTypes.length; i++) {
      if (i != 0) {
        buffer.write(' || ');
      }
      _writeTypeCheckCondition(buffer, valueCode, _mapType([unionTypes[i]]));
    }
    buffer.write(')');
  } else {
    throw 'Unable to type check $valueCode against $dartType';
  }
}

class IndentableStringBuffer extends StringBuffer {
  int _indentLevel = 0;
  int _indentSpaces = 2;

  int get totalIndent => _indentLevel * _indentSpaces;
  String get _indentString => ' ' * totalIndent;

  void indent() => _indentLevel++;
  void outdent() => _indentLevel--;

  void writeIndented(Object obj) {
    write(_indentString);
    write(obj);
  }

  void writeIndentedln(Object obj) {
    write(_indentString);
    writeln(obj);
  }

  void writeIndentedlnIf(bool condition, Object obj) {
    if (condition) {
      writeIndentedln(obj);
    }
  }
}
