import 'dart:ffi';

import 'package:ffi/ffi.dart';
import 'package:segmentation_douglas_peucker_flutter/dali_point.dart';
import 'package:segmentation_douglas_peucker_flutter/dotnet_exception.dart';
import 'package:segmentation_douglas_peucker_flutter/gen/generated_bindings.dart';
import 'package:segmentation_douglas_peucker_flutter/lib.dart';

abstract class Douglas {
  static List<DaliPoint> transformDouglasPeucker(
      List<DaliPoint> originePoints) {
    final NativeLibrary nativeLibrary =
        NativeLibrary(Lib.init('Dali.Segmentation.DouglasPeucker'));

    final Pointer<System_Exception_t> exception = calloc();

    final System_Type_t type = nativeLibrary.System_Drawing_Point_TypeOf();

    final System_Collections_Generic_List_A1_t points =
        nativeLibrary.System_Collections_Generic_List_A1_Create_1(
      type,
      originePoints.length,
      exception,
    );

    for (final point in originePoints) {
      final System_Drawing_Point_t nativePoint =
          nativeLibrary.System_Drawing_Point_Create(
        point.x,
        point.y,
        exception,
      );

      exception.handle();
      nativeLibrary.System_Collections_Generic_List_A1_Add(
          points, type, nativePoint, exception);
      exception.handle();
    }

    final douglasPeuckerList = nativeLibrary
        .DALI_Segmentation_SegmentationDouglasPeucker_DouglasPeuckerReduction(
      points,
      1,
      exception,
    );
    exception.handle();

    final count = nativeLibrary.System_Collections_Generic_List_A1_Count_Get(
      douglasPeuckerList,
      type,
      exception,
    );
    exception.handle();

    final List<DaliPoint> dartList = [];

    for (int i = 0; i < count; i++) {
      final douglasPoint =
          nativeLibrary.System_Collections_Generic_List_A1_Item_Get(
        douglasPeuckerList,
        type,
        i,
        exception,
      );

      exception.handle();
      dartList.add(
        DaliPoint.fromPointer(douglasPoint),
      );
    }

    return dartList;
  }
}
