///
/// Created by @Haoyi on 2021/7/16
///

part of '../visual_feast_engine.dart';

class _SortingLayers {
  final List<RenderLayer> renderLayers = <RenderLayer>[RenderLayer.invalid];

  // Use Binary Search
  int _nearest(int low, int high, RenderElement renderObj) {
    if (low > high) {
      return -low;
    }
    while (low <= high) {
      final int mid = (low + high) >> 1;
      if (renderObj.orderInLayer == renderLayers[mid].order) {
        return mid;
      } else if (renderObj.orderInLayer < renderLayers[mid].order) {
        return _nearest(low, mid - 1, renderObj);
      } else {
        return _nearest(mid + 1, high, renderObj);
      }
    }
    return -low;
  }

  _SortingLayers();

  bool get isEmpty => renderLayers.isEmpty;

  void _frameUpdate(double t) {
    for (var renderLayer in renderLayers) {
      renderLayer.frameUpdate(t);
    }
  }

  void _render(Canvas canvas) {
    for (var renderLayer in renderLayers) {
      renderLayer.render(canvas);
    }
  }

  void attachRender(RenderElement renderObj) {
    final index = _nearest(1, renderLayers.length - 1, renderObj);
    if (index >= 0) {
      renderLayers[index].addRender(renderObj);
    } else {
      final layer = RenderLayer(renderObj.orderInLayer);
      layer.addRender(renderObj);
      if (renderLayers.isEmpty) {
        renderLayers.add(layer);
      } else {
        renderLayers.insert(-index, layer);
      }
    }
    renderObj.dispatchAttach();
  }

  void detachRender(RenderElement renderObj) {
    final index = _nearest(1, renderLayers.length - 1, renderObj);
    if (index >= 0) {
      renderLayers[index].removeRender(renderObj);
      if (renderLayers[index].isEmpty) {
        renderLayers.removeAt(index);
      }
    }
  }

  void detachAll() {
    for (var layer in renderLayers) {
      layer.removeAll();
    }
    renderLayers.clear();
    renderLayers.add(RenderLayer.invalid);
  }
}
