from os.path import join, exists, isdir, relpath, abspath, dirname
import datetime as dt
import posixpath
import logging
import tempfile
from os import stat, makedirs, remove
import random
import uuid
from cStringIO import StringIO
import time

from six import string_types
try:
    import gevent
except:
    gevent = None
from ..clients.http import Client
from .. import settings
from ..serialization import deserializer, serializer
from ..errors import KitchenSinkError
from ..utils.pathutils import urlsplit, dirsplit, urljoin
from .catalog import _write, _read
logger = logging.getLogger(__name__)



## should factor this out into a separate module
class RemoteData(object):
    """RemoteData objects can contain raw data (in memory, in self._raw,
    or on disk, in self._local_path.  Or as a deserialized object, in
    self._obj.

    Maybe this isn't the greatest approach, mixing them all together in one object
    but that's what we have for now.  Currently, if you ask for self.obj(), or
    self.local_path(), or self.raw(), we will retrieve it from what we perceive
    to be the cheapest source.  For example, if you have the stream in memory
    (self._raw), and you ask for the local path, we will write it to a temp file
    and return you that path
    """
    def __init__(self, obj=None, local_path=None, data_url=None,
                 raw=None,
                 rpc_url=None,
                 fmt="cloudpickle"):
        if rpc_url is None:
            rpc_url = settings.data_rpc_url
        self.rpc_url = rpc_url
        self.data_url = data_url
        self.fmt = fmt
        self._obj = obj
        self._local_path = local_path
        self._raw = raw

    def __setstate__(self, obj):
        self.data_url = obj['data_url']
        self.fmt = obj['fmt']
        self.rpc_url = settings.data_rpc_url
        self._obj = None
        self._local_path = None
        self._raw = None

    def __getstate__(self):
        return dict(data_url=self.data_url,
                    fmt=self.fmt)

    def client(self, rpc_url=None):
        if rpc_url is None:
            rpc_url = self.rpc_url
        return Client(rpc_url, rpc_name='data', queue_name='data')

    def _get_stream(self):
        """returns either the stream associated with a data_url