// Copyright (c) 2022, 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.

// There is no public API exposed yet, the in-progress API lives here.
import 'dart:async';

import 'package:macros/macros.dart';

/*macro*/ class Observable implements FieldDeclarationsMacro {
  const Observable();

  @override
  Future<void> buildDeclarationsForField(
      FieldDeclaration field, MemberDeclarationBuilder builder) async {
    var name = field.identifier.name;
    if (!name.startsWith('_')) {
      throw ArgumentError(
          '@observable can only annotate private fields, and it will create '
          'public getters and setters for them, but the public field '
          '$name was annotated.');
    }
    var publicName = name.substring(1);
    var getter = DeclarationCode.fromParts([
      '  ',
      field.type.code,
      ' get $publicName => ',
      field.identifier,
      ';',
    ]);
    builder.declareInType(getter);

    var print =
        // ignore: deprecated_member_use
        await builder.resolveIdentifier(Uri.parse('dart:core'), 'print');
    var setter = DeclarationCode.fromParts([
      '  set $publicName(',
      field.type.code,
      ' val) {\n    ',
      print,
      "('Setting $publicName to \${val}');\n    ",
      field.identifier,
      ' = val;\n  }',
    ]);
    builder.declareInType(setter);
  }
}
