import 'dart:async';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

import '../models/ink_point.dart';
import '../models/pen_tool.dart';
import '../models/pointer_device_kind.dart';

class PenInputService {
  final StreamController<InkPoint> _pointController =
      StreamController<InkPoint>.broadcast();

  Stream<InkPoint> get pointStream => _pointController.stream;

  PenTool currentTool = PenTool.pen;
  Color currentColor = Colors.black;
  double currentStrokeWidth = 2.0;

  void addPoint(InkPoint point) {
    _pointController.add(point);
  }

  InputDeviceKind mapFlutterKind(PointerDeviceKind kind) {
    switch (kind) {
      case PointerDeviceKind.touch:
        return InputDeviceKind.touch;
      case PointerDeviceKind.mouse:
        return InputDeviceKind.mouse;
      case PointerDeviceKind.stylus:
        return InputDeviceKind.stylus;
      case PointerDeviceKind.invertedStylus:
        return InputDeviceKind.invertedStylus;
      case PointerDeviceKind.trackpad:
        return InputDeviceKind.trackpad;
      case PointerDeviceKind.unknown:
        return InputDeviceKind.unknown;
    }
  }

  InkPoint fromPointerEvent(PointerEvent event) {
    // Devices without real pressure support (mouse, basic touch) report a
    // degenerate range where pressureMin == pressureMax, which can yield a
    // pressure of 0.0 and produce zero-width strokes. In that case fall back
    // to a neutral mid-pressure value so strokes remain visible.
    final pressure = event.pressureMin == event.pressureMax
        ? 0.5
        : event.pressure;
    return InkPoint(
      x: event.localPosition.dx,
      y: event.localPosition.dy,
      pressure: pressure,
      tilt: event is PointerMoveEvent ? event.tilt : 0.0,
      timestamp: event.timeStamp.inMicroseconds,
      pointerDeviceKind: mapFlutterKind(event.kind),
    );
  }

  void dispose() {
    _pointController.close();
  }
}
