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

class Data extends ChangeNotifier {
  // Configuration available values
  List _availableLangValues = ['fr'];
  List _availableWordLengthValues = ['4', '5', '6', '7', '8'];
  List _availableLevelValues = ['easy', 'normal'];
  List _availableSkinValues = ['default'];

  List get availableLangValues => _availableLangValues;
  List get availableWordLengthValues => _availableWordLengthValues;
  List get availableLevelValues => _availableLevelValues;
  List get availableSkinValues => _availableSkinValues;

  // Application default configuration
  String _lang = '';
  String _langDefault = 'fr';
  String _length = '';
  String _lengthDefault = '5';
  String _level = '';
  String _levelDefault = 'normal';
  String _skin = '';
  String _skinDefault = 'default';

  // Game data
  bool _gameIsRunning = false;
  bool _foundWord = false;
  String _word = '';
  final int _recentWordsCount = 20;
  List _recentWords = [];
  List<String> _guesses = [];
  String _currentGuess = '';
  String _foundLetters = '';
  int _maxGuessesCount = 7;

  String get lang => _lang;
  void updateLang(String lang) {
    _lang = lang;
    notifyListeners();
  }

  String get length => _length;
  void updateLength(String length) {
    _length = length;
    notifyListeners();
  }

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

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

  List<String> get guesses => _guesses;
  String get currentGuess => _currentGuess;
  int get maxGuessesCount => _maxGuessesCount;
  void currentGuessAddLetter(String letter) {
    if (_currentGuess.length < int.parse(_length)) {
      _currentGuess = _currentGuess + letter;
      notifyListeners();
    }
  }

  void currentGuessRemoveLetter() {
    if (_currentGuess.length > 0) {
      _currentGuess = _currentGuess.substring(0, _currentGuess.length - 1);
      notifyListeners();
    }
  }

  void currentGuessSubmitWord() {
    if (_currentGuess.length == int.parse(_length)) {
      print('check word: ' + _currentGuess);
      if (_currentGuess != _word) {
        print('wrong');
      } else {
        print('ok found');
        _foundWord = true;
      }
      addGuess(_currentGuess);
      notifyListeners();
    }
  }

  void currentGuessSubmitWrongWord() {
    print('Adding unknown word');
    addGuess(_currentGuess);
    notifyListeners();
  }

  void addGuess(String word) {
    print('addGuess(' + word + ')');
    _guesses.add(word);
    _currentGuess = '';
  }

  String get foundLetters => _foundLetters;
  void initFoundLetters() {
    _foundLetters = _word.substring(0, 1).padRight(_word.length, ' ');
  }

  void addFoundLetter(String letter, int i) {
    _foundLetters = _foundLetters.substring(0, i) + letter + _foundLetters.substring(i + 1);
    print('Found a "' + letter + '" => "' + _foundLetters + '".');
  }

  bool get gameWon => _foundWord;

  getParameterValue(String parameterCode) {
    switch (parameterCode) {
      case 'lang':
        {
          return _lang;
        }
      case 'length':
        {
          return _length;
        }
      case 'level':
        {
          return _level;
        }
      case 'skin':
        {
          return _skin;
        }
    }
  }

  List getParameterAvailableValues(String parameterCode) {
    switch (parameterCode) {
      case 'lang':
        {
          return _availableLangValues;
        }
      case 'length':
        {
          return _availableWordLengthValues;
        }
      case 'level':
        {
          return _availableLevelValues;
        }
      case 'skin':
        {
          return _availableSkinValues;
        }
    }
    return [];
  }

  setParameterValue(String parameterCode, String parameterValue) async {
    switch (parameterCode) {
      case 'lang':
        {
          updateLang(parameterValue);
        }
        break;
      case 'length':
        {
          updateLength(parameterValue);
        }
        break;
      case 'level':
        {
          updateLevel(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('lang', prefs.getString('lang') ?? _langDefault);
    setParameterValue('length', prefs.getString('length') ?? _lengthDefault);
    setParameterValue('level', prefs.getString('level') ?? _levelDefault);
    setParameterValue('skin', prefs.getString('skin') ?? _skinDefault);
  }

  bool get gameIsRunning => _gameIsRunning;
  void updateGameIsRunning(bool gameIsRunning) {
    _gameIsRunning = gameIsRunning;
    notifyListeners();
  }

  bool isGameFinished() {
    print('isGameFinished');

    if (_foundWord || (_guesses.length > (_maxGuessesCount - 1))) {
      return true;
    }

    return false;
  }

  String get word => _word;

  void updateWord(String word) {
    _word = word;
    if (word != '') {
      _recentWords.insert(0, word);
      _recentWords = _recentWords.take(_recentWordsCount).toList();
    }
    initFoundLetters();
    notifyListeners();
  }

  bool isRecentlyPicked(String word) {
    return _recentWords.contains(word);
  }

  void resetGame() {
    _word = '';
    _guesses = [];
    _currentGuess = '';
    _foundWord = false;
    notifyListeners();
  }
}