import json
import string
import random

from eve.utils import ParsedRequest
from eve.io.mongo import MongoJSONEncoder

from apps.dictionaries.service import words, DictionaryService, store_dict, fetch_dict, FILE_ID
from superdesk import get_resource_service
from superdesk.tests import TestCase


class WordsTestCase(TestCase):
    def setUp(self):
        self.req = ParsedRequest()
        with self.app.test_request_context(self.app.config.get("URL_PREFIX")):
            self.dictionaries = [
                {"_id": "1", "name": "Eng", "language_id": "en"},
                {"_id": "2", "name": "Eng AUs", "language_id": "en-AU", "is_active": "true"},
                {"_id": "3", "name": "French", "language_id": "fr"},
            ]
            self.app.data.insert("dictionaries", self.dictionaries)

    def test_words_parsing(self):
        self.assertEqual(["abc"], words("abc"))
        self.assertEqual(["abc bce"], words("abc bce"))
        self.assertEqual(["abc bce", "wer tyu"], words("abc bce\nwer tyu"))
        self.assertEqual(["you'd"], words("you'd"))
        self.assertEqual(["you'd", "will"], words("you'd\nwill"))

    def test_base_language(self):
        self.assertEqual(DictionaryService().get_base_language("en-AU"), "en")
        self.assertIsNone(DictionaryService().get_base_language("en"))

    def test_get_dictionary(self):
        with self.app.app_context():
            dicts = get_resource_service("dictionaries").get_dictionaries("en")
            self.assertEqual(len(dicts), 1)
            self.assertEqual(dicts[0]["language_id"], "en")
            dicts = get_resource_service("dictionaries").get_dictionaries("en-AU")
            self.assertEqual(len(dicts), 1)
            self.assertEqual(dicts[0]["language_id"], "en-AU")

    def test_store_dict_small(self):
        content = {"foo": 1}
        dictionary = {"content": content}
        store_dict(dictionary, {})
        self.assertEqual(json.dumps(content), dictionary.get("content"))
        self.assertEqual(content, fetch_dict(dictionary))

    def test_store_dict_big(self):
        content = self._get_big_dict()
        dictionary = {"content": content}
        self.assertGreater(len(json.dumps(dictionary, cls=MongoJSONEncoder)), 1000000)
        store_dict(dictionary, {})
        self.assertIsNone(dictionary["content"])
        self.assertEqual(content, fetch_dict(dictionary))
        self.assertLess(len(json.dumps(dictionary, cls=MongoJSONEncoder)), 100)

    def test_store_big_after_small(self):
        original = {"content": {"foo": 1}}
        updates = {"content": self._get_big_dict()}
        store_dict(updates, original)
        self.assertIsNone(updates["content"])
        self.assertIsNotNone(updates[FILE_ID])

    def test_small_after_big(self):
        updates = {"content": self._get_big_dict()}
        store_dict(updates, {})
        file_id = updates[FILE_ID]
        self.assertIsNotNone(self.app.storage.get(file_id))

        original = updates
        updates = {"content": {"foo": 1}}
        store_dict(updates, original)

        self.assertIsNone(updates[FILE_ID])
        self.assertEqual(json.dumps({"foo": 1}), updates["content"])
        self.assertIsNone(self.app.storage.get(file_id))

    def _get_big_dict(self):
        word = "".join([random.choice(string.ascii_letters) for i in range(1000000)])
        return {word: 1}
