import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'package:sendtrain/database/database.dart';

class ActivityTimerModel with ChangeNotifier {
  int _actionCounter = 0;
  Activity? _activity;
  List _sets = [];
  // List _actions = [];
  int _currentActionNum = 0;
  int _currentSetNum = 0;
  Timer? _periodicTimer;
  double _progress = 0;
  ItemScrollController? _isc;
  int _totalTime = 0;

  int get actionCount => _actionCounter;
  int get currentActionNum => _currentActionNum;
  dynamic get currentAction => currentSet.isNotEmpty ? currentSet[_currentActionNum] : {};
  int get currentSetNum => _currentSetNum;
  dynamic get currentSet => _sets.isNotEmpty ? _sets[_currentSetNum] : {};
  Activity? get activity => _activity;
  List get sets => _sets;
  Timer? get periodicTimer => _periodicTimer;
  bool get isActive => _isActive();
  double get progress => _progress;
  int get totalTime => _totalTime;

  void setup(Activity activity, List actions) {
    if (_activity == null || activity.id != _activity?.id) {
      _periodicTimer?.cancel();
      _progress = 0;
      _isc = null;
      _activity = activity;
      // only one action for now
      _sets = actions.isNotEmpty ? json.decode(actions[0].set) : [];
      // _actions = actions;
      _currentActionNum = 0;
      _currentSetNum = 0;
      setActionCount();
      getTotalTime();
    }

    moveToIndex(_currentSetNum);
  }

  void getTotalTime() {
    int time = 0;
    for(int setIndex = 0; _sets.length > setIndex; setIndex++) {
      for (int actionIndex = 0; _sets[setIndex].length > actionIndex; actionIndex++) {
        var action = _sets[setIndex][actionIndex];
        if (action['type'] == 'seconds') {
          time = time + action['amount'] as int;
        }
      }
    }

    _totalTime = time;
  }

  void reset() {
    _progress = 0;
    _currentActionNum = 0;
    _currentSetNum = 0;
    _periodicTimer!.cancel();
    setActionCount();
    moveToIndex(0);
  }

  void setScrollController(ItemScrollController isc) {
    _isc = isc;
  }

  bool isCurrentItem(int setNum, int actionNum) {
    if (setNum == _currentSetNum && actionNum == _currentActionNum) {
      return true;
    }

    return false;
  }

  int totalActions() {
    int count = 0;
    for (int i = 0; i < _sets.length; i++) {
      count = count + _sets[i].length as int;
    }

    return count;
  }

  void setActionCount() {
    _actionCounter = currentAction.isNotEmpty ? currentAction['amount'] : 0;
  }

  void pause() {
    _periodicTimer!.cancel();
    notifyListeners();
  }

  void start() {
    _periodicTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
      switch (currentAction['type']) {
        // we don't want to count down
        // if its repititions
        case 'repititions':
          break;
        case 'seconds':
          if (_actionCounter > 0) {
            _actionCounter--;
            _totalTime--;
          } else {
            nextAction(_currentActionNum + 1);
            setActionCount();
          }
          updateProgress();
      }

      notifyListeners();
    });
  }

  void updateProgress() {
    _progress = (currentAction['actionID'] +
            (1.0 - _actionCounter / currentAction['amount'])) /
        totalActions();
    notifyListeners();
  }

  void setAction(int setNum, int actionNum, String type) {
    _currentActionNum = actionNum;
    _currentSetNum = setNum;
    notifyListeners();
    moveToIndex(_currentSetNum);
  }

  void nextAction(int nextActionIndex) {
    if (currentSet.length > nextActionIndex) {
      setAction(_currentSetNum, nextActionIndex, 'automatic');
    } else if (_sets.length > _currentSetNum + 1) {
      // if the item isn't in the set
      // increment the set and reset action index
      setAction(_currentSetNum + 1, 0, 'automatic');
    } else {
      // if we're done all the sets
      // cancel timer and reset activity
      reset();
    }
  }

  void moveToIndex(int index) {
    if (_isc != null && _isc!.isAttached) {
      _isc?.scrollTo(
          index: index,
          duration: Duration(milliseconds: 500),
          curve: Curves.easeInOutCubic);
    }
  }

  bool _isActive() {
    return (_periodicTimer != null && _periodicTimer!.isActive) ? true : false;
  }
}
