#!/usr/bin/env python
# encoding: utf-8

"""
flask_hal.link
==============

Implements the ``HAL`` Link specification.
"""

# Standard Libs
import json


VALID_LINK_ATTRS = [
    'name',
    'title',
    'type',
    'deprecation',
    'profile',
    'templated',
    'hreflang'
]


class Links(object):
    """Build a collection of ``HAL`` link objects.

    Example:
        >>> from flask_hal.link import Link, Links
        >>> l = Links(
        ...     Link('foo', 'http://foo.com'),
        ...     Link('bar', 'http://bar.com'))
        >>> print l.to_json()
        ... {
        ...     "_links": {
        ...         "foo": {
        ...             "href": "http://foo.com"
        ...         },
        ...         "bar": {
        ...             "href": "http://bar.com"
        ...         }
        ...     }
        ... }
    """

    def __init__(self, *args):
        """Initialise a new ``Links`` object.

        Example:
            >>> l = Links(
            ...     Link('foo', 'http://foo.com'),
            ...     Link('bar', 'http://bar.com'))

        Raises:
            TypeError: If a link is not a ``flask_hal.link.Link`` instance
        """

        self.links = []
        self.index = 0

        for link in args:
            if not isinstance(link, Link):
                raise TypeError(
                    '{0} is not a valid flask_hal.link.Link instance'.format(link))

            self.links.append(link)

    def __getitem__(self, index):
        """Get a specific link by index.
        """

        return self.links[index]

    def __iter__(self):
        """Makes the ``Links`` object iterable.
        """

        return self

    def __len__(self):
        """Returns the number of links.
        """

        return len(self.links)

    def __next__(self):
        """Iterate to the next item.

        Returns:
            Link: The next link object

        Raises:
            StopIteration
        """

        try:
            link = self.links[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1

        return link

    def next(self):
        """Support for Python 2.x iterators.
        """

        return self.__next__()

    def append(self, link):
        """Appends a ``Link`` object to the ``Links``.

        Args:
            link (flask_hal.link.Link): The ``Link`` object to add

        Raises:
            TypeError: If the ``link`` argument is not a ``flask_hal.link.Link``
        """

        if not isinstance(link, Link):
            raise TypeError(
                '{0} is not a valid flask_hal.link.Link instance'.format(link))

        self.links.append(link)


class Link(object):
    """Build ``HAL`` specification ``_links`` object.

    Example:
        >>> from flask_hal.link import Link
        >>> l = Link('foo', 'http://foo.com/bar')
        >>> print l.to_json()
        ... '{"foo": {"href": "http://foo.com/bar"}}'
        >>> l.title = 'Foo'
        >>> print l.to_json()
        ... '{"foo": {"href": "http://foo.com/bar", "name": "Foo"}}'

    """

    def __init__(self, rel, href, **kwargs):
        """Initialise a new ``Link`` object.

        Args:
            rel (str): The links ``rel`` or name
            href (str): The URI to the resource

        Keyword Args:
            name (str): The links name attribute, optional
            title (str): The links title attribute, optional
            type (str): The links type attribute, optional
            deprecation (str): The deprecation attribute, optional
            profile (str): The profile  attribute, optional
            templated (bool): The templated attribute, optional
            hreflang (str): The hreflang attribute, optional
        """

        self.rel = rel
        self.href = href

        for attr in VALID_LINK_ATTRS:
            if attr in kwargs:
                setattr(self, attr, kwargs.pop(attr))

    def to_json(self):
        """Returns the ``JSON`` encoded representation of the ``Link`` object.

        Example:
            >>> from flask_hal.link import Link
            >>> l = Link('foo', 'http://foo.com', name='Foo')
            >>> print l.to_json()
            ... '{"foo": {"href": "http://foo.com", "name": "Foo"}}'

        Returns:
            str: The ``JSON`` encoded object
        """

        # Minimum viable link
        link = {
            'href': self.href
        }

        # Add extra attributes if they exist
        for attr in VALID_LINK_ATTRS:
            if hasattr(self, attr):
                link[attr] = getattr(self, attr)

        return json.dumps({self.rel: link})

@@ -3939,20 +3939,20 @@
  def to_
-json
+dict
 (self):%0A
@@ -3974,32 +3974,31 @@
 rns the 
-%60%60JSON%60%60 encoded
+Python %60%60dict%60%60
  represe
@@ -4013,38 +4013,40 @@
 of the %60%60Link%60%60 
-object
+instance
 .%0A%0A        Examp
@@ -4149,20 +4149,8 @@
 com'
-, name='Foo'
 )%0A  
@@ -4162,32 +4162,26 @@
      %3E%3E%3E
- print
  l.to_
-json
+dict
 ()%0A     
@@ -4191,35 +4191,34 @@
     ... 
+%7B
 '
-%7B%22
 foo
-%22: %7B%22
+': %7B'
 href
-%22: %22
+': '
 http://f
@@ -4223,35 +4223,19 @@
 /foo.com
-%22, %22name%22: %22Foo%22
+'
 %7D%7D
-'
 %0A%0A      
@@ -4261,38 +4261,10 @@
     
-str: The %60%60JSON%60%60 encoded obje
+di
 ct%0A 
@@ -4551,33 +4551,495 @@
 urn 
-json.dumps(%7Bself.rel: link%7D
+%7B%0A            self.rel: link%0A        %7D%0A%0A    def to_json(self):%0A        %22%22%22Returns the %60%60JSON%60%60 encoded representation of the %60%60Link%60%60 object.%0A%0A        Example:%0A            %3E%3E%3E from flask_hal.link import Link%0A            %3E%3E%3E l = Link('foo', 'http://foo.com', name='Foo')%0A            %3E%3E%3E print l.to_json()%0A            ... '%7B%22foo%22: %7B%22href%22: %22http://foo.com%22, %22name%22: %22Foo%22%7D%7D'%0A%0A        Returns:%0A            str: The %60%60JSON%60%60 encoded object%0A        %22%22%22%0A%0A        return json.dumps(self.to_dict()
 )%0A

Add to_dict method on Link and convert to_json to use new to_dict