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

class Data extends ChangeNotifier {

  // Configuration available values
  List _availableDifficultyLevels = ['easy', 'medium', 'hard', 'nightmare'];
  List _availableSizes = ['10x10', '15x15', '20x20'];
  List _availableSkins = ['default'];

  List get availableDifficultyLevels => _availableDifficultyLevels;
  List get availableSizes => _availableSizes;
  List get availableSkins => _availableSkins;

  // Application default configuration
  String _level = null;
  String _levelDefault = 'medium';
  String _size = null;
  String _sizeDefault = '15x15';
  String _skin = null;
  String _skinDefault = 'default';

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

  String get level => _level;
  void updateLevel(String level) {
    _level = level;
    notifyListeners();
  }

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

  String get skin => _skin;
  void updateSkin(String skin) {
    _skin = skin;
    notifyListeners();
  }

  getParameterValue(String parameterCode) {
    switch(parameterCode) {
      case 'difficulty': { return _level; }
      break;
      case 'size': { return _size; }
      break;
      case 'skin': { return _skin; }
      break;
    }
  }

  List getParameterAvailableValues(String parameterCode) {
    switch(parameterCode) {
      case 'difficulty': { return _availableDifficultyLevels; }
      break;
      case 'size': { return _availableSizes; }
      break;
      case 'skin': { return _availableSkins; }
      break;
    }
  }

  setParameterValue(String parameterCode, String parameterValue) async {
    switch(parameterCode) {
      case 'difficulty': { updateLevel(parameterValue); }
      break;
      case 'size': { updateSize(parameterValue); }
      break;
      case 'skin': { updateSkin(parameterValue); }
      break;
    }
    final prefs = await SharedPreferences.getInstance();
    prefs.setString(parameterCode, parameterValue);
  }

  void initParametersValues() async {
    final prefs = await SharedPreferences.getInstance();
    setParameterValue('difficulty', prefs.getString('difficulty') ?? _levelDefault);
    setParameterValue('size', prefs.getString('size') ?? _sizeDefault);
    setParameterValue('skin', prefs.getString('skin') ?? _skinDefault);
  }

  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;
    updateReportMode(false);
    notifyListeners();
  }

  bool get gameRunning => _gameRunning;
  void updateGameRunning(bool gameRunning) {
    _gameRunning = gameRunning;
    updateGameWin(false);
    updateGameFail(false);
    notifyListeners();
  }

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

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

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

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

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