import 'package:fis_common/event/event_type.dart';
import 'package:fis_measure/interfaces/enums/items.dart';
import 'package:fis_measure/interfaces/process/calculators/calculator.dart';
import 'package:fis_measure/interfaces/process/items/item.dart';
import 'package:fis_measure/interfaces/process/items/item_feature.dart';
import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
import 'package:flutter/foundation.dart';

import 'item_feature.dart';

abstract class MeasureItem<T extends MeasureItemFeature> extends IMeasureItem {
  late final ItemMeta _meta;
  late final IMeasureItem? _parent;
  ItemStates _state = ItemStates.waiting;
  ICalculator? _calculator;
  T? _feature;
  final List<IMeasureItemFeature> _measuredFeatures = [];

  MeasureItem(ItemMeta meta, [IMeasureItem? parent]) {
    _parent = parent;
    _meta = meta;
  }

  @override
  String get briefAnnotation => meta.getItem("BriefAnnotation");

  @override
  String get description => meta.getItem("Description");

  @override
  T? get feature => _feature;
  @protected
  set feature(T? value) {
    if (value != _feature) {
      _feature = value;
    }
  }

  @override
  String get workingFormular => meta.getItem("WorkingFormular");

  @override
  ICalculator? get calculator => _calculator;
  @protected
  set calculator(ICalculator? value) {
    if (value != _calculator) {
      _calculator = value;
    }
  }

  @override
  IMeasureItem? get parent => _parent;

  @override
  ItemMeta get meta => _meta;

  @override
  ItemStates get state => _state;
  @protected
  set state(ItemStates value) {
    if (value != _state) {
      _state = value;
    }
  }

  @override
  late final featureUpdated = FEventHandler<IMeasureItemFeature?>();

  @override
  bool execute(PointInfo args) {
    bool result = false;
    if (state == ItemStates.waiting ||
        state == ItemStates.running ||
        state == ItemStates.finished) {
      switch (args.pointType) {
        case PointInfoType.mouseUp:
        case PointInfoType.mouseDown:
        case PointInfoType.mouseMove:
          result = onExecuteMouse(args);
          break;
        case PointInfoType.touchUp:
        case PointInfoType.touchDown:
        case PointInfoType.touchMove:
          result = onExecuteTouch(args);
          break;
      }
    }

    if (result) {
      /// 通知刷新
      doFeatureUpdate();
    }
    return result;
  }

  @protected
  void doFeatureUpdate() {
    featureUpdated.emit(this, feature);
  }

  @protected
  void doFeatureFinish() {
    if (feature != null) {
      feature!.isActive = false;
      measuredFeatures.add(feature!);
      if (calculator != null && calculator!.output != null) {
        calculator!.outputs.add(calculator!.output!);
      }
    }
    feature = null;
    state = ItemStates.finished;
  }

  @protected
  void doCalculate() {
    calculator?.calculate();
    // print(calculator?.output?.description);
  }

  @protected
  bool onExecuteMouse(PointInfo args);
  @protected
  bool onExecuteTouch(PointInfo args);

  @override
  List<IMeasureItemFeature> get measuredFeatures => _measuredFeatures;
}
