import 'package:fis_common/logger/logger.dart';
import 'package:fis_measure/interfaces/date_types/rect.dart';
import 'package:fis_measure/interfaces/enums/display_mode.dart';
import 'package:fis_measure/interfaces/enums/visual_area_type.dart';
import 'package:fis_measure/interfaces/mode_names.dart';

import 'section.dart';
import 'view_port.dart';

class LayoutConfiguration {
  static LayoutConfiguration? _instance;

  static LayoutConfiguration get ins {
    _instance ??= LayoutConfiguration();
    return _instance!;
  }

  bool _loaded = false;
  final List<LayoutSection> _layoutSections = [];

  bool get loaded => _loaded;

  LayoutConfiguration();

  void loadData(List<dynamic> data) {
    if (_loaded) return;

    for (final item in data) {
      final Map<String, dynamic> map = item;
      _layoutSections.add(LayoutSection.fromJson(map));
    }
    if (_layoutSections.isEmpty) {
      throw ArgumentError(
          "Layout configuration error: LayoutSection not found.");
    }
    _loaded = true;
  }

  DRect getRect(
    String section,
    VisualAreaTypeEnum areaType,
    DisplayModeEnum displayFormat,
  ) {
    String mode;
    switch (areaType) {
      case VisualAreaTypeEnum.tissue:
      case VisualAreaTypeEnum.flow:
        mode = ModeNames.B;
        break;
      case VisualAreaTypeEnum.timeMotion:
      case VisualAreaTypeEnum.tissueTimeMotion:
        mode = ModeNames.TM;
        break;
      case VisualAreaTypeEnum.doppler:
        mode = ModeNames.Doppler;
        break;
      case VisualAreaTypeEnum.trace:
        mode = ModeNames.Trace;
        break;
      case VisualAreaTypeEnum.colorbar:
        mode = ModeNames.P_ColorBar;
        break;
      case VisualAreaTypeEnum.tissue3D:
        mode = ModeNames.FourD;
        break;
      case VisualAreaTypeEnum.sweiReliableColorBar:
        mode = ModeNames.P_SweiReliableColorBar;
        break;
    }

    final viewPort = _matchViewPort(section, mode, displayFormat);
    final rect = DRect(
        viewPort.left / 100,
        viewPort.top / 100,
        (viewPort.right - viewPort.left) / 100,
        (viewPort.bottom - viewPort.top) / 100);
    return rect;
  }

  LayoutViewPort _matchViewPort(
    String name,
    String layoutKey,
    DisplayModeEnum displayFormat,
  ) {
    bool found = false;
    LayoutViewPort viewPort = LayoutViewPort();
    List<LayoutSection> sections = [];

    final sectionIdx = _layoutSections.indexWhere((x) => x.key == name);
    if (sectionIdx > -1) {
      sections.add(_layoutSections[sectionIdx]);
    }
    sections.add(_layoutSections[0]);

    for (final candidate in sections) {
      final layoutIdx = candidate.layouts.indexWhere((x) => x.key == layoutKey);
      if (layoutIdx > -1) {
        final layout = candidate.layouts[layoutIdx];
        int i = -1;
        while (++i < layout.viewPorts.length) {
          if (layout.viewPorts[i].displayFormat == displayFormat) {
            break;
          }
        }

        if (i == layout.viewPorts.length) {
          i = 0;
        }
        viewPort = layout.viewPorts[i];
        found = true;
        break;
      }
    }

    if (!found) {
      logger.w(
          "MatchViewPort failed, ViewPort:$viewPort is used. layout section:$name, layout key:$layoutKey, display format:${displayFormat.name}.");
    }

    return viewPort;
  }
}
