# -*- coding: utf-8 -*-
import io
import six

from .decoder import PVLDecoder
from .encoder import PVLEncoder
from ._collections import (
    PVLModule,
    PVLGroup,
    PVLObject,
    Units,
)

__author__ = 'The PlanetaryPy Developers'
__email__ = 'trevor@heytrevor.com'
__version__ = '0.1.0'
__all__ = [
    'load',
    'loads',
    'dump',
    'dumps',
    'PVLModule',
    'PVLGroup',
    'PVLObject',
    'Units',
]


def load(stream, cls=PVLDecoder, **kwargs):
    """Deserialize ``stream`` as a pvl module.

    :param stream: a ``.read()``-supporting file-like object containing a
        module. if ``stream`` is a string it will be treated as a filename

    :param cls: the decoder class used to deserialize the pvl module. You may
        use the default ``PVLDecoder`` class or provide a custom sublcass.

    :param **kwargs: the keyword arguments to pass to the decoder class.
    """
    if isinstance(stream, six.string_types):
        with open(stream, 'rb') as fp:
            return cls(**kwargs).decode(fp)
    return cls(**kwargs).decode(stream)


def loads(data, cls=PVLDecoder, **kwargs):
    """Deserialize ``data`` as a pvl module.

    :param data: a pvl module as a byte or unicode string

    :param cls: the decoder class used to deserialize the pvl module. You may
        use the default ``PVLDecoder`` class or provide a custom sublcass.

    :param **kwargs: the keyword arguments to pass to the decoder class.
    """
    if not isinstance(data, bytes):
        data = data.encode('utf-8')
    return cls(**kwargs).decode(data)


def dump(module, stream, cls=PVLEncoder, **kwargs):
    """Serialize ``module`` as a pvl module to the provided ``stream``.

    :param module: a ```PVLModule``` or ```dict``` like object to serialize

    :param stream: a ``.write()``-supporting file-like object to serialize the
        module to

    :param cls: the encoder class used to serialize the pvl module. You may use
        the default ``PVLEncoder`` class or provided encoder formats such as the
        ```IsisCubeLabelEncoder``` and ```PDSLabelEncoder``` classes. You may
        also provided a custom sublcass of ```PVLEncoder```

    :param **kwargs: the keyword arguments to pass to the encoder class.
    """
    if isinstance(stream, six.string_types):
        with open(stream, 'wb') as fp:
            return cls(**kwargs).encode(module, fp)
    cls(**kwargs).encode(module, stream)


def dumps(module, cls=PVLEncoder, **kwargs):
    """Serialize ``module`` as a pvl module formated byte string.

    :param module: a ```PVLModule``` or ```dict``` like object to serialize

    :param cls: the encoder class used to serialize the pvl module. You may use
        the default ``PVLEncoder`` class or provided encoder formats such as the
        ```IsisCubeLabelEncoder``` and ```PDSLabelEncoder``` classes. You may
        also provided a custom sublcass of ```PVLEncoder```

    :param **kwargs: the keyword arguments to pass to the encoder class.

    :returns: a byte string encoding of the pvl module
    """
    stream = io.BytesIO()
    cls(**kwargs).encode(module, stream)
    return stream.getvalue()


# Depreciated aliases
# TODO: add warnings for these?
Label = PVLModule
LabelGroup = PVLGroup
LabelObject = PVLObject
LabelEncoder = PVLEncoder
LabelDecoder = PVLEncoder

@@ -17,16 +17,1065 @@
 f-8 -*-%0A
+%22%22%22Python implementation of PVL (Parameter Value Language).%0A%0APVL is a markup language, similar to xml, commonly employed for entries in the%0APlanetary Database System used by NASA to store mission data, among other uses.%0AThis package supports both encoding a decoding a superset of PVL, including the%0AUSGS Isis Cube Label and NASA PDS 3 Label dialects.%0A%0ABasic Usage%0A-----------%0A%0ADecoding pvl modules::%0A%0A    %3E%3E%3E import pvl%0A    %3E%3E%3E module = pvl.loads('''%0A    ...   foo = bar%0A    ...   items = (1, 2, 3)%0A    ...   END%0A    ... ''')%0A    %3E%3E%3E print module%0A    PVLModule(%5B%0A      (u'foo', u'bar')%0A      (u'items', %5B1, 2, 3%5D)%0A    %5D)%0A    %3E%3E%3E print module%5B'foo'%5D%0A    bar%0A%0AEncoding pvl modules::%0A%0A    %3E%3E%3E import pvl%0A    %3E%3E%3E print pvl.dumps(%7B%0A    ...   'foo': 'bar',%0A    ...   'items': %5B1, 2, 3%5D%0A    ... %7D)%0A    items = (1, 2, 3)%0A    foo = bar%0A    END%0A%0ABuilding pvl modules::%0A%0A    %3E%3E%3E import pvl%0A    %3E%3E%3E module = pvl.PVLModule(%7B'foo': 'bar'%7D)%0A    %3E%3E%3E module.append('items', %5B1, 2, 3%5D)%0A    %3E%3E%3E print pvl.dumps(module)%0A    foo = bar%0A    items = (1, 2, 3)%0A    END%0A%22%22%22%0A
 import i
@@ -1648,17 +1648,17 @@
 module. 
-i
+I
 f %60%60stre
@@ -2885,24 +2885,24 @@
 rialize the%0A
-
         modu
@@ -2906,16 +2906,76 @@
 odule to
+. If %60%60stream%60%60 is a string it will be treated as a filename
 %0A%0A    :p

Add module docs.