from __future__ import unicode_literals
from xml.etree import ElementTree as ET
import datetime

import boto3
from moto.core import BaseBackend, BaseModel

from .resources import VOICE_DATA
from .utils import make_arn_for_lexicon

DEFAULT_ACCOUNT_ID = 123456789012


class Lexicon(BaseModel):
    def __init__(self, name, content, region_name):
        self.name = name
        self.content = content
        self.size = 0
        self.alphabet = None
        self.last_modified = None
        self.language_code = None
        self.lexemes_count = 0
        self.arn = make_arn_for_lexicon(DEFAULT_ACCOUNT_ID, name, region_name)

        self.update()

    def update(self, content=None):
        if content is not None:
            self.content = content

        # Probably a very naive approach, but it'll do for now.
        try:
            root = ET.fromstring(self.content)
            self.size = len(self.content)
            self.last_modified = int(
                (
                    datetime.datetime.now() - datetime.datetime(1970, 1, 1)
                ).total_seconds()
            )
            self.lexemes_count = len(root.findall("."))

            for key, value in root.attrib.items():
                if key.endswith("alphabet"):
                    self.alphabet = value
                elif key.endswith("lang"):
                    self.language_code = value

        except Exception as err:
            raise ValueError("Failure parsing XML: {0}".format(err))

    def to_dict(self):
        return {
            "Attributes": {
                "Alphabet": self.alphabet,
                "LanguageCode": self.language_code,
                "LastModified": self.last_modified,
                "LexemesCount": self.lexemes_count,
                "LexiconArn": self.arn,
                "Size": self.size,
            }
        }

    def __repr__(self):
        return "<Lexicon {0}>".format(self.name)


class PollyBackend(BaseBackend):
    def __init__(self, region_name=None):
        super(PollyBackend, self).__init__()
        self.region_name = region_name

        self._lexicons = {}

    def reset(self):
        region_name = self.region_name
        self.__dict__ = {}
        self.__init__(region_name)

    def describe_voices(self, language_code, next_token):
        if language_code is None:
            return VOICE_DATA

        return [item for item in VOICE_DATA if item["LanguageCode"] == language_code]

    def delete_lexicon(self, name):
        # implement here
        del self._lexicons[name]

    def get_lexicon(self, name):
        # Raises KeyError
        return self._lexicons[name]

    def list_lexicons(self, next_token):

        result = []

        for name, lexicon in self._lexicons.items():
            lexicon_dict = lexicon.to_dict()
            lexicon_dict["Name"] = name

            result.append(lexicon_dict)

        return result

    def put_lexicon(self, name, content):
        # If lexicon content is bad, it will raise ValueError
        if name in self._lexicons:
            # Regenerated all the stats from the XML
            # but keeps the ARN
            self._lexicons.update(content)
        else:
            lexicon = Lexicon(name, content, region_name=self.region_name)
            self._lexicons[name] = lexicon


available_regions = boto3.session.Session().get_available_regions("polly")
polly_backends = {
    region: PollyBackend(region_name=region) for region in available_regions
}
