import 'dart:async';
import 'package:html/parser.dart';
import 'package:html/dom.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/services.dart';
import 'dart:math' show Random;
import 'package:diacritic/diacritic.dart';

import '../words/list_french_words.dart';

class RandomPick {
  final String level;
  RandomPick(this.level);

  String _url;
  String _word;
  String _clue;
  final random = Random();

  init() async {
    switch (level) {
      case 'Thèmes':
        await wordFromLocal();
        break;
      case 'Avancé':
        _url =
            'https://www.palabrasaleatorias.com/mots-aleatoires.php?fs=1&fs2=0&Submit=Nouveau+mot';
        await wordFromWeb(_url);
        break;
      case 'Junior':
        _url =
            'https://www.palabrasaleatorias.com/mots-aleatoires.php?fs=1&fs2=1&Submit=Nouveau+mot';
        await wordFromWeb(_url);
        break;
      case 'Expert':
        await wordFromPackage();
        break;
      default:
        await wordFromLocal();
    }
  }

  Future<void> wordFromWeb(String url) async {
    try {
      var response = await http.Client().get(Uri.parse(url));
      if (response.statusCode == 200) {
        var html = parse(utf8.decode(response.bodyBytes));
        Element element = html.getElementsByTagName('div').last;
        String word = _validate(element.text);
        if (word == null) {
          throw Exception();
        }
        _word = word;
      } else {
        throw Exception();
      }
    } catch (e) {
      _word = null;
    }
  }

  String _validate(String word) {
    String wordToValidate = word.trim();
    if (wordToValidate.contains(' ')) {
      return null;
    }
    wordToValidate = removeDiacritics(wordToValidate);
    wordToValidate = wordToValidate.toUpperCase();
    wordToValidate = wordToValidate.replaceAll(RegExp('[0-9]'), '');
    wordToValidate = wordToValidate.replaceAll(RegExp('[^A-Z]'), '');
    if (wordToValidate.length < 3 || wordToValidate.length > 12) {
      return null;
    }
    return wordToValidate;
  }

  Future _waitList() => Future(() {
        final completer = Completer();
        int indexRandom = random.nextInt(list_french_words.length);
        completer.complete(list_french_words.sublist(indexRandom, indexRandom + 1).join('\n'));
        return completer.future;
      });

  wordFromPackage() async {
    var wordList = await _waitList();
    var word = _validate(wordList);
    _word = word;
  }

  Future<void> wordFromLocal() async {
    String jsonString;
    try {
      jsonString = await rootBundle.loadString('assets/files/word-list-fr.json');
      final jsonResponse = await json.decode(jsonString);
      var wordList = jsonResponse[jsonResponse.keys.toList().join()];
      int randomCategoryIndex = random.nextInt(wordList.length);
      _clue = wordList[randomCategoryIndex]['clue'];
      List<String> words = [];
      for (var word in wordList[randomCategoryIndex]['words']) {
        words.add(word);
      }
      String word = words[random.nextInt(words.length)];
      _word = word ?? 'UNEXPECTED ERROR';
    } catch (e) {
      _word = 'UNEXPECTED ERROR';
    }
  }

  String get word => _word;

  String get clue => _clue;
}