import 'package:ecosim/src/common/models/pvector.dart';
import 'package:ecosim/src/seeking/models/seeking_boid.dart';
import 'package:ecosim/src/ecosim/models/boid.dart';
import 'package:ecosim/src/ecosim/models/boid_base.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

import 'dart:math' as math;

import 'models/pointer_indicator.dart';

class SeekingSimulation extends ChangeNotifier {
  final TickerProvider vsync;
  late Ticker _ticker;
  BuildContext context;
  final List<Boid> boids = [];
  PointerIndicator pointerIndicator = PointerIndicator(
    position: PVector(
      0.0,
      0.0,
    ),
  );

  SeekingSimulation(this.vsync, this.context) {
    _ticker = vsync.createTicker(_onEachTick)..start();
    final rng = math.Random();
    final screenSize = MediaQuery.of(context).size;
    int followBoidsCount = 1;
    int avoidBoidsCount = 500;

    for (var i = 0; i < followBoidsCount; i++) {
      double x = rng.nextDouble() * screenSize.width / 2;
      double y = rng.nextDouble() * screenSize.height / 2;
      boids.add(
        SeekingBoid(
          position: PVector(x, y),
          velocity: PVector(0, -2),
          tickDamage: 0,
          health: 100,
          maxHealth: 100,
          replicationProbability: 0,
          birthTimestamp: 0,
          dna: BoidBaseDna(
            steeringForce: 0.01,
            speed: 2,
            foodPull: 1,
            poisonPull: 0,
            predatorPull: 0,
            foodPerceptionRadius: 1000,
            poisonPerceptionRadius: 0,
            predatorPerceptionRadius: 0,
            mutationThreshold: 1,
          ),
          healthyColor: Colors.white,
          unhealthyColor: Colors.red,
          r: 8,
          mutationThreshold: 1,
        ),
      );
    }
    for (var i = 0; i < avoidBoidsCount; i++) {
      double x = rng.nextDouble() * screenSize.width;
      double y = rng.nextDouble() * screenSize.height;
      boids.add(
        SeekingBoid(
          position: PVector(x, y),
          velocity: PVector(0, -2),
          tickDamage: 0,
          health: 100,
          maxHealth: 100,
          replicationProbability: 0,
          birthTimestamp: 0,
          dna: BoidBaseDna(
            steeringForce: 0.01,
            speed: 2,
            foodPull: -1,
            poisonPull: 0,
            predatorPull: 0,
            foodPerceptionRadius: 150,
            poisonPerceptionRadius: 0,
            predatorPerceptionRadius: 0,
            mutationThreshold: 1,
          ),
          healthyColor: Colors.red,
          unhealthyColor: Colors.red,
          r: 8,
          mutationThreshold: 1,
        ),
      );
    }
  }

  void _onEachTick(Duration deltaTime) {
    for (var i = boids.length - 1; i >= 0; i--) {
      final screenSize = MediaQuery.of(context).size;
      // boids[i].boundaries(screenSize);
      // boids[i].seek(pointerIndicator.position);
      boids[i].update();
      boids[i].updateBoidDirection(
        [
          [
            pointerIndicator,
          ]
        ],
        screenSize,
      );
      // boundary check before and after updateBoidTransform
      // to override it. The priority of the world collision
      // check has to be higher
      boids[i].boundaryBoidsDirectionUpdate(screenSize);
      boids[i].updateBoidTransform();
      boids[i].boundaryBoidsDirectionUpdate(screenSize);
    }
    notifyListeners();
  }

  @override
  void dispose() {
    _ticker.dispose();
    super.dispose();
  }
}
