import 'package:flutter/material.dart';
import 'package:flut/flut/object.dart';
import 'package:flut/flut/runtime.dart';
import 'package:flut/flut/error.dart';

class _FlutTextEditingController extends TextEditingController {
  final FlutRuntime _runtime;
  final String? _buildTextSpanId;

  _FlutTextEditingController({
    required FlutRuntime runtime,
    super.text,
    String? buildTextSpanId,
  }) : _runtime = runtime,
       _buildTextSpanId = buildTextSpanId;

  @override
  TextSpan buildTextSpan({
    required BuildContext context,
    TextStyle? style,
    required bool withComposing,
  }) {
    final buildTextSpanId = _buildTextSpanId;
    if (buildTextSpanId != null) {
      final decoded = _runtime.callAction<TextSpan>(
        buildTextSpanId,
        args: [text],
      );
      if (decoded != null) {
        return TextSpan(style: style, children: [decoded]);
      }
    }
    return super.buildTextSpan(
      context: context,
      style: style,
      withComposing: withComposing,
    );
  }
}

class FlutTextEditingController
    extends FlutRealtimeObject<TextEditingController> {
  FlutTextEditingController._({
    required FlutRuntime runtime,
    required Map<String, dynamic> json,
    required TextEditingController target,
  }) : super(
         runtime: runtime,
         json: json,
         type: 'TextEditingController',
         target: target,
       );

  static FlutTextEditingController flutDecode(
    FlutRuntime runtime,
    Map<String, dynamic> json,
  ) {
    return FlutTextEditingController._(
      runtime: runtime,
      json: json,
      target: _FlutTextEditingController(
        runtime: runtime,
        text: runtime.unpackOptionalField<String>(json, 'text'),
        buildTextSpanId: runtime.unpackOptionalField<String>(
          json,
          'buildTextSpanId',
        ),
      ),
    );
  }

  @override
  dynamic getRawProperty(String property) {
    switch (property) {
      case 'text':
        return flutTarget.text;
    }
    throw FlutUnknownPropertyException('TextEditingController', property);
  }

  @override
  bool setProperty(String property, dynamic value) {
    switch (property) {
      case 'text':
        flutTarget.text = (value as String?) ?? '';
        return true;
    }
    throw FlutUnknownPropertyException('TextEditingController', property);
  }

  @override
  dynamic callMethod(String method, Map<String, dynamic> args) {
    throw FlutUnknownMethodException(method);
  }
}
