
import 'dart:async';
import 'dart:core';
import 'dart:math' as math;
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';


class Plot extends StatefulWidget {
  const Plot({
    super.key,
    required this.title,
    required this.aspectRatio,
    required this.maxTimeSeconds,
    required this.readAnalog,
    required this.minY,
    required this.maxY,
    required this.sampleTimeMicross});
  final String title;
  final double aspectRatio;
  final double maxTimeSeconds;
  final Future<double> Function() readAnalog;
  final int sampleTimeMicross;
  final double minY;
  final double maxY;
  @override
    State<StatefulWidget> createState() => _Plot();
}

class _Plot extends State<Plot> {
  late Timer timer;
  late int limit= ((widget.maxTimeSeconds)/(widget.sampleTimeMicross/1000)).toInt();
  late List<FlSpot> adc = <FlSpot>[const FlSpot( 0, 0)];
  int index = 0;
  double el = 0.0;
  double valPrev = 0;

  late Logger log;

  @override
    void dispose() {
      super.dispose();
      timer.cancel();
    }

  @override
    void initState() {
      super.initState();
      log = Logger("Plot : ${widget.title}");
      log.info('limit : $limit');
      timer = Timer.periodic(Duration(microseconds: widget.sampleTimeMicross), (timer) {
          widget.readAnalog().then((val){
              if (index>=limit) {
		             log.info('================================================================ reset $index : $el : ${index != 0 ? adc[index-1] : 0}');
		             index = 0;
		             el = 0.0;
		             adc.clear();
              }
              setState(() {
                 el = (index * widget.sampleTimeMicross)/1000;
                 adc.add(FlSpot( el, val));
                 log.info('================================================================ $index : $el : ${adc[index]}');
                 index +=1;
                 });
              });
          });
    }

  @override
    Widget build(BuildContext context) {
      return AspectRatio(
          aspectRatio: widget.aspectRatio,
          child : LineChart(
            LineChartData(
            minY: widget.minY,
            maxY: widget.maxY,
//             minY: -0.5,
//             maxY: 0.5,
              minX: 0,
              maxX: widget.maxTimeSeconds.toDouble(),
              lineBarsData: [LineChartBarData(
                spots: adc,
                dotData: const FlDotData(
                  show: false,
                  ),
                barWidth: 2,
                isCurved: false,
                )],
              titlesData: const FlTitlesData(show: true, 
                 rightTitles: AxisTitles(sideTitles: SideTitles(reservedSize: 40, showTitles: false)),
                 topTitles: AxisTitles(sideTitles: SideTitles(reservedSize: 40, showTitles: false)),
              ),
              gridData: const FlGridData(show: true, drawVerticalLine: false),
              )
            )
          );
    }
}

class DummyData {
  late int limitCount;
  late List<FlSpot> sinPoints;
  double xValue = 0;
  double step = 0.05;
  int index = 0;
  late Timer timer;
  late void Function() stateChange;

  DummyData(){
    limitCount = (20/step).toInt();
    sinPoints = List<FlSpot>.generate(limitCount+1, (index) => FlSpot(index+step,0));
  }

  void begin(Function() sc) {
    stateChange = sc;
    timer = Timer.periodic(const Duration(milliseconds: 2), (timer) {
        stateChange.call();
        if (xValue >= 20) {
          xValue = 0;
          index = 0;
          sinPoints.clear();
        } else {
          xValue += step;
          index += 1;
        }
        // print("$index : $xValue");
        });
  }

  void update(){
    sinPoints.insert(index, FlSpot(xValue, 1 - (math.Random(xValue.toInt()).nextDouble()*2)));
  }
}
