# -*- coding: utf-8 -*-
import cStringIO

from datetime import timedelta, datetime
from django.conf import settings
from django.test.client import Client
from .base import BaseStaticSiteRenderer

from boto.s3.connection import S3Connection

__all__ = ('S3StaticSiteRenderer', )


class BucketCache(object):
    BUCKET_CACHE = {}
    CONN = None

    @classmethod
    def s3_conn(cls):
        if not cls.CONN:
            cls.CONN = S3Connection(
                aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
                aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY
            )
        return cls.CONN

    @classmethod
    def _get_bucket(cls, bucket=None):
        if bucket in cls.BUCKET_CACHE:
            return cls.BUCKET_CACHE[bucket]
        if not bucket:
            bucket = settings.MEDUSA_AWS_STORAGE_BUCKET_NAME or settings.AWS_STORAGE_BUCKET_NAME
        cls.BUCKET_CACHE[bucket] = cls.s3_conn().get_bucket(bucket)
        cls.BUCKET_CACHE[bucket].configure_website("index.html", "500.html")
        return cls.BUCKET_CACHE[bucket]


def _get_cf():
    from boto.cloudfront import CloudFrontConnection
    return CloudFrontConnection(
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
        aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY
    )


def _get_distribution():
    if not getattr(settings, "AWS_DISTRIBUTION_ID", None):
        return None

    conn = _get_cf()
    try:
        return conn.get_distribution_info(settings.AWS_DISTRIBUTION_ID)
    except:
        return None


def _upload_to_s3(key, file):
    key.set_contents_from_file(file, policy="public-read")
    cache_time = 0
    now = datetime.now()
    expire_dt = now + timedelta(seconds=cache_time * 1.5)
    if cache_time != 0:
        key.set_metadata(
            'Cache-Control',
            'max-age=%d, must-revalidate' % int(cache_time)
        )
        key.set_metadata(
            'Expires',
            expire_dt.strftime("%a, %d %b %Y %H:%M:%S GMT")
        )
    key.make_public()


def _s3_render_path(args):
    client, path, view = args
    if not client:
        client = Client()

    # Render the view
    # If path is a tuple or a list
    # It means that django-hosts is installed
    if isinstance(path, dict):
        host = ".".join((path["host"], settings.PARENT_HOST))
        bucket = BucketCache._get_bucket(path.get("bucket", None))
        path = path["path"]
    else:
        host = None
        bucket = BucketCache._get_bucket()

    if host:
        resp = client.get(path, HTTP_HOST=host)
    else:
        resp = client.get(path)

    if resp.status_code != 200:
        raise Exception('path {} has returned a {} code'.format(path, resp.status_code))

    # Default to "index.html" as the upload path if we're in a dir listing.
    outpath = path
    if path.endswith("/"):
        outpath += "index.html"
    if outpath.startswith('/'):
        outpath = outpath[1:]

    key = bucket.get_key(outpath) or bucket.new_key(outpath)
    key.content_type = resp['Content-Type']

    temp_file = cStringIO.StringIO(resp.content)
    md5 = key.compute_md5(temp_file)

    # If key is new, there's no etag yet
    if not key.etag:
        _upload_to_s3(key, temp_file)
        message = "Creating"

    else:
        etag = key.etag or ''
        # for some weird reason, etags are quoted, strip them
        etag = etag.strip('"').strip("'")
        if etag not in md5:
            #_upload_to_s3(key, temp_file)
            message = "Updating"
        else:
            message = "Skipping"

    print "%s http://%s%s" % (
        message,
        bucket.get_website_endpoint(),
        outpath
    )
    temp_file.close()
    return [path, outpath]


class S3StaticSiteRenderer(BaseStaticSiteRenderer):
    """
    A variation of BaseStaticSiteRenderer that deploys directly to S3
    rather than to the local filesystem.

    Requires `boto`.

    Uses some of the same settings as `django-storages`:
      * AWS_ACCESS_KEY
      * AWS_SECRET_ACCESS_KEY
      * AWS_STORAGE_BUCKET_NAME
    """
    @classmethod
    def initialize_output(cls):
        cls.all_generated_paths = []

    @property
    def s3_conn(self):
        if not hasattr(self, '_s3_conn'):
            self._s3_conn = S3Connection(
                aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
                aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
                is_secure=False
            )
        return self._s3_conn

    def generate(self):
        self.generated_paths = []
        if getattr(settings, "MEDUSA_MULTITHREAD", False):
            # Upload up to ten items at once via `multiprocessing`.
            from multiprocessing import Pool
            import itertools

            print "Uploading with up to 10 upload processes..."
            pool = Pool()
            path_tuples = pool.map(
                _s3_render_path,
                ((None, path, None) for path in self.paths),
                chunksize=5
            )
            pool.close()
            pool.join()
            self.generated_paths = list(itertools.chain(*path_tuples))
        else:
            # Use standard, serial upload.
            self.client = Client()
            for path in self.paths:
                self.generated_paths += _s3_render_path((self.client, path, None))

        type(self).all_generated_paths += self.generated_paths

    @staticmethod
    def _final_s3_path(path):
        if isinstance(path, dict):
            bucket = path.get('bucket', settings.MEDUSA_AWS_STORAGE_BUCKET_NAME)
            return ''.join((bucket, path["path"]))
        return path

    @classmethod
    def finalize_output(cls):
        dist = _get_distribution()
        if dist and dist.in_progress_invalidation_batches < 3:
            cf = _get_cf()
            req = cf.create_invalidation_request(
                settings.AWS_DISTRIBUTION_ID,
                cls.all_generated_paths
            )
            print req.id
            #import time
            #while True:
            #    status = cf.invalidation_request_status(
            #        settings.AWS_DISTRIBUTION_ID,
            #        req.id
            #    ).status
            #    if status != "InProgress":
            #        print
            #        print "Complete:"
            #        if dist.config.cnames:
            #            print "Site deployed to http://%s/" % dist.config.cnames[0]
            #        else:
            #            print "Site deployed to http://%s/" % dist.domain_name
            #        print
            #        break
            #    else:
            #        print "In progress..."
            #    time.sleep(5)

@@ -3422,17 +3422,16 @@
         
-#
 _upload_

remove comment on pushing where updating a document