import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

class Data extends ChangeNotifier {

  // Configuration available values
  List _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare'];
  List _availableSizeValues = ['10x10', '15x15', '20x20'];
  List _availableSkinValues = ['default'];

  List get availableLevelValues => _availableLevelValues;
  List get availableSizeValues => _availableSizeValues;
  List get availableSkinValues => _availableSkinValues;

  // Application default configuration
  String _parameterLevel = '';
  String _parameterLevelDefault = 'medium';
  String _parameterSize = '';
  String _parameterSizeDefault = '15x15';
  String _parameterSkin = '';
  String _parameterSkinDefault = 'default';

  // Application current configuration
  String get parameterLevel => _parameterLevel;
  String get parameterSize => _parameterSize;
  String get parameterSkin => _parameterSkin;

  // Game data
  bool _assetsPreloaded = false;
  bool _gameIsRunning = false;
  bool _animationInProgress = false;
  int _sizeVertical = 0;
  int _sizeHorizontal = 0;
  List _cells = [];
  bool _isBoardMined = false;
  int _minesCount = 0;
  bool _reportMode = false;
  bool _gameWin = false;
  bool _gameFail = false;

  void updateParameterLevel(String parameterLevel) {
    _parameterLevel = parameterLevel;
    notifyListeners();
  }

  int get sizeVertical => _sizeVertical;
  int get sizeHorizontal => _sizeHorizontal;
  void updateParameterSize(String parameterSize) {
    _parameterSize = parameterSize;
    _sizeHorizontal = int.parse(_parameterSize.split('x')[0]);
    _sizeVertical = int.parse(_parameterSize.split('x')[1]);
    notifyListeners();
  }

  void updateParameterSkin(String parameterSkin) {
    _parameterSkin = parameterSkin;
    notifyListeners();
  }

  String getParameterValue(String parameterCode) {
    switch(parameterCode) {
      case 'level': { return _parameterLevel; }
      break;
      case 'size': { return _parameterSize; }
      break;
      case 'skin': { return _parameterSkin; }
      break;
    }
    return '';
  }

  List getParameterAvailableValues(String parameterCode) {
    switch(parameterCode) {
      case 'level': { return _availableLevelValues; }
      break;
      case 'size': { return _availableSizeValues; }
      break;
      case 'skin': { return _availableSkinValues; }
      break;
    }
    return [];
  }

  setParameterValue(String parameterCode, String parameterValue) async {
    switch(parameterCode) {
      case 'level': { updateParameterLevel(parameterValue); }
      break;
      case 'size': { updateParameterSize(parameterValue); }
      break;
      case 'skin': { updateParameterSkin(parameterValue); }
      break;
    }
    final prefs = await SharedPreferences.getInstance();
    prefs.setString(parameterCode, parameterValue);
  }

  void initParametersValues() async {
    final prefs = await SharedPreferences.getInstance();
    setParameterValue('level', prefs.getString('level') ?? _parameterLevelDefault);
    setParameterValue('size', prefs.getString('size') ?? _parameterSizeDefault);
    setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault);
  }

  bool get gameIsRunning => _gameIsRunning;
  void updateGameIsRunning(bool gameIsRunning) {
    _gameIsRunning = gameIsRunning;
    updateGameWin(false);
    updateGameFail(false);
    updateReportMode(false);
    notifyListeners();
  }

  bool get gameWin => _gameWin;
  void updateGameWin(bool gameWin) {
    _gameWin = gameWin;
    notifyListeners();
  }

  bool get gameFail => _gameFail;
  void updateGameFail(bool gameFail) {
    _gameFail = gameFail;
    notifyListeners();
  }

  List get cells => _cells;
  void updateCells(List cells) {
    _cells = cells;
    notifyListeners();
  }

  void setCellAsExplored(int row, int col) {
    _cells[row][col].isExplored = true;
    _cells[row][col].isMarked = false;
    if (_cells[row][col].isMined) {
      _cells[row][col].isExploded = true;
    };

    notifyListeners();
  }

  void toggleCellMark(int row, int col) {
    _cells[row][col].isMarked = !_cells[row][col].isMarked;
    notifyListeners();
  }

  bool get assetsPreloaded => _assetsPreloaded;
  void updateAssetsPreloaded(bool assetsPreloaded) {
    _assetsPreloaded = assetsPreloaded;
  }


  bool get isBoardMined => _isBoardMined;
  void updateIsBoardMined(bool isBoardMined) {
    _isBoardMined = isBoardMined;
    notifyListeners();
  }

  int get minesCount => _minesCount;
  void updateMinesCount(int minesCount) {
    _minesCount = minesCount;
  }


  bool get reportMode => _reportMode;
  void updateReportMode(bool reportMode) {
    _reportMode = reportMode;
    notifyListeners();
  }

  bool get animationInProgress => _animationInProgress;
  void updateAnimationInProgress(bool animationInProgress) {
    _animationInProgress = animationInProgress;
    notifyListeners();
  }

  void setAnimatedBackground(List animatedCellsPattern) {
    for (var row = 0; row < _sizeVertical; row++) {
      for (var col = 0; col < _sizeHorizontal; col++) {
        _cells[row][col].isAnimated = animatedCellsPattern[row][col];
      }
    }
    notifyListeners();
  }
  void resetAnimatedBackground() {
    for (var row = 0; row < _sizeVertical; row++) {
      for (var col = 0; col < _sizeHorizontal; col++) {
        _cells[row][col].isAnimated = false;
      }
    }
  }
}