# Copyright (c) Sunlight Labs, 2012 under the terms and conditions
# of the LICENSE file.

import sunlight.service
from sunlight.errors import BadRequestException
import json

module_name = "openstates"
service_url = "http://openstates.org/api/v1"

class openstates(sunlight.service.Service):
    """
    Bindings into the `Open States API <http://openstates.org/api/>`_. Keep in
    mind this is a thin wrapper around the API so the API documentation is the
    place to look for help on field names and examples.
    """

    def all_metadata(self, **kwargs):
        """
        Get an overview of all available states including each state's name
        and abbreviation.

        For details see
        `Metadata Overview <http://openstates.org/api/metadata/#metadata-overview>`_.
        """
        return self.get(["metadata"], **kwargs)

    def state_metadata(self, state, **kwargs):
        """
        Complete metadata for a given state, containing information on
        the particulars of this state's chambers, sessions, and terms.

        For details see
        `State Metadata <http://openstates.org/api/metadata/#state-metadata>`_.
        """
        return self.get(["metadata", state], **kwargs)

    def bills(self, **kwargs):
        """
        Search the entirety of bills available via the Open States API.

        The fields and keyword arguments can be found on the
        `Bill API docs <http://openstates.org/api/bills/>`_.
        """
        return self.get(["bills"], **kwargs)

    def bill(self, bill_id, **kwargs):
        """
        Get full information on a single bill from the Open States API given
        the OpenStates Bill ID (such as TNB00004685)

        `Bill API docs <http://openstates.org/api/bills/>`_.
        """
        return self.get(["bills", bill_id], **kwargs)

    def bill_detail(self, state, session, bill_id, chamber=None):
        """
        Get full information on a single bill from the Open States API given
        a ``state``, ``session``, and ``bill_id`` (and optionally ``chamber``
        if the request would be ambiguous without one).

        The fields and keyword arguments can be found on the
        `Open States Bill API docs <http://openstates.org/api/bills/>`_.
        """
        lss = ["bills", state, session]
        if chamber:
            lss.append(chamber)
        lss.append(bill_id)
        return self.get(lss)

    def legislators(self, **kwargs):
        """
        Search the entirety of legislators available via the Open States API.

        The fields and keyword arguments can be found on the
        `Legislator API docs <http://openstates.org/api/legislators/>`_.
        """
        return self.get( [ "legislators"], **kwargs )

    def legislator_detail(self, leg_id, **kwargs):
        """
        Get detailed information on a single legislator given their Open States
        Legislator ID.

        The ``leg_id`` argument is a legislator ID code used throughout the
        Open States API, such as ``MDL000210``.

        For details on fields see the `Legislator API Fields
        <http://openstates.org/api/legislators/#legislator-fields>`_.
        """
        return self.get(["legislators", leg_id], **kwargs)

    def legislator_geo_search(self, latitude, longitude, **kwargs):
        """
        Given a latitude and longitude return all legislators that represent
        districts containing that point.

        See the Open States documentation for examples of `Legislator Geo
        Lookup <http://openstates.org/api/legislators/#geo-lookup>`_.
        """
        kwargs['lat']  = latitude
        kwargs['long'] = longitude
        return self.get(["legislators", "geo"], **kwargs)

    def committees(self, **kwargs):
        """
        Search against all committees available via the Open States API.

        Committee fields and keyword arguments can be found on the
        `Committee API docs <http://openstates.org/api/committees/>`_.
        """
        return self.get(["committees"], **kwargs)

    def committee_detail(self, committee_id, **kwargs):
        """
        Get detailed information on a single committee given its Open States
        Committee ID.

        The ``committee_id`` argument is a committee ID code used throughout
        the Open States API, such as ``MDC000065``.

        For details on fields see the `Committee API Fields
        <http://openstates.org/api/committees/#committee-fields>`_.
        """
        return self.get(["committees", committee_id], **kwargs)

    def events(self, **kwargs):
        """
        Query the Open States API for information regarding upcoming events
        taken from a state-level legislative calendar.

        See the Open States' site for details on the
        `Event API <http://openstates.org/api/events/>`_.
        """
        return self.get([ "events" ], **kwargs)

    def event_detail(self, event_id, **kwargs):
        """
        Get detailed informaton regarding a single event.

        ``event_id`` is an OpenStates event ID, such as ``TXE00000990``.

        See the Open States' site for details on the
        `Event API Fields <http://openstates.org/api/events/#event-fields>`_.
        """
        lss = [ "events", event_id ]
        return self.get( lss, **kwargs )

    def districts(self, state, chamber=None, **kwargs):
        """
        Get a listing of districts for a state (optionally narrowed by
        chamber).

        For a listing of fields see `District Fields
        <http://openstates.org/api/districts/#district-fields>`_.
        """
        pieces = ['districts', state]
        if chamber:
            pieces.append(chamber)
        return self.get(pieces, **kwargs)

    def district_boundary(self, boundary_id, **kwargs):
        """
        Get a detailed GeoJSON-style boundary for a given district given a
        boundary_id (available via the :meth:``districts``.

        ``boundary_id`` resembles ``sldl-tx-state-house-district-35``.

        For a listing of fields see `District Fields
        <http://openstates.org/api/districts/#district-fields>`_.

        For more information on this method and example output see
        `District Boundary Lookup
        <http://openstates.org/api/districts/#district-boundary-lookup>`_
        """
        return self.get(['districts', 'boundary', boundary_id], **kwargs)

    # API impl methods

    def _get_url(self, objs, apikey, **kwargs):
        # Gate for any None's in the query. This is usually a problem.
        if None in objs:
            raise BadRequestException("`None' passed to the URL encoder (%s)" %
                                      (str(objs)))

        # join pieces by slashes and add a trailing slash
        object_path = "/".join(objs)
        object_path +=  "/"

        return "%s/%s?apikey=%s&%s" % (
            service_url,
            object_path,
            apikey,
            sunlight.service.safe_encode(kwargs)
        )

    def _decode_response(self, response):
        return json.loads(response)
