import requests
import xmltodict


from .history import NanoHistorySequence as History


class NanoBase(object):
    """Base object for pynano API objects.

    This object implements the common functionality for fetching and processing
    API data from the NaNoWriMo API.
    """

    # API name for this object
    _name = None

    # Endpoint URLs for this object; must include a '{name}' placeholder
    _primary_url = None
    _history_url = None

    # Caches for retrieved data
    _data = None
    _history = None

    def __init__(self, name, prefetch=False):
        """Initialize a new pynano API object.

        The only required parameter is name, which is the name of the current
        object as recognized by the backend API.

        If prefetch is set to True, the API will be queried immediately; if not,
        it will be lazily fetched on first use.
        """

        self._name = name

        if prefetch:
            self._fetch()

    def history(self, day):
        """Retrieve historical data for the given day."""
        return self._fetch_day(day)

    def _fetch_element(self, index):
        """Get a particular data element, fetching from the API if necessary."""
        try:
            # Attempt to return the requested data element
            return self._data[index]
        except (KeyError, TypeError):
            # Didn't find it, or nothing fetched yet
            # Fetch data from the API
            self._fetch()

            # If we still don't find it, allow the exception to be raised
            return self._data[index]

    def _fetch_day(self, day):
        """Retrieve data for a particular day from the API."""
        if self._history is None:
            # Haven't fetched history data yet, do so now
            self._fetch(True)

        # Retrieve the day's data
        return self._history[day]

    def _fetch(self, history=False):
        """Fetch data from the API.

        If the history parameter is True, then the history URL will be queried
        for data; if it is False, then the primary URL will be queried.
        """
        if history:
            # Fetching history data
            url = self._history_url
        else:
            # Fetching primary data
            url = self._primary_url

        # Now fetch from the server
        r = requests.get(url.format(name=self._name))
        # Parse the returned data (removing root element)
        data = next(iter(xmltodict.parse(r.text).values()))

        # Now stash the data
        if history:
            # Stash the history data
            self._history = self._process_history(data['wordcounts'])

            if self._data is None:
                # Haven't fetched primary data, stash what we got
                del data['wordcounts']
                self._data = data
        else:
            # Stash the primary data
            self._data = data

    def _process_history(self, history_data):
        """Process the history API's data into an easily-indexed dict."""
        processed = {}

        for data in history_data['wcentry']:
            date = data['wcdate'].split('-')
            if date[1] != '11':
                # Do nothing if we somehow got non-November data
                continue

            # Index the data by day less 1 (0-indexed data)
            processed[int(date[2])-1] = data

        return History(processed)


@@ -952,24 +952,38 @@
 f._fetch()%0A%0A
+    @property%0A
     def hist
@@ -986,29 +986,24 @@
 history(self
-, day
 ):%0A        %22
@@ -1008,18 +1008,9 @@
  %22%22%22
-Retrieve h
+H
 isto
@@ -1030,59 +1030,280 @@
 r th
-e given day.%22%22%22%0A        return self._fetch_day(day)
+is object.%0A%0A        The returned object is a NanoHistorySequence object.%0A        %22%22%22%0A        if self._history is None:%0A            # Haven't fetched history data yet, do so now%0A            self._fetch(True)%0A%0A        # Return the history object%0A        return self._history
 %0A%0A  
@@ -1799,294 +1799,8 @@
 x%5D%0A%0A
-    def _fetch_day(self, day):%0A        %22%22%22Retrieve data for a particular day from the API.%22%22%22%0A        if self._history is None:%0A            # Haven't fetched history data yet, do so now%0A            self._fetch(True)%0A%0A        # Retrieve the day's data%0A        return self._history%5Bday%5D%0A%0A
     

Make history a property, returns the history object