from datetime import datetime
import os
import logging

from django.conf.urls import url
from django.contrib.auth.decorators import login_required
from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage
from django.db.models import get_model
from django.http import HttpResponse, HttpResponseNotFound
from annoying.decorators import render_to
from django.shortcuts import render_to_response
from django.utils import simplejson
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views.decorators.http import require_POST
from jfu.http import upload_receive, UploadResponse

from core.utils import live
from dss import localsettings, settings
from spa.models import UserProfile, Release
from spa.models.mix import Mix
from spa.models.comment import Comment
from core.serialisers import json
from core.tasks import create_waveform_task
from spa.models.notification import Notification


logger = logging.getLogger(__name__)


class AjaxHandler(object):
    # Get an instance of a logger

    def __init__(self, api_name="v1"):
        self.api_name = api_name

    @property
    def urls(self):
        pattern_list = [
            url(r'^mix/add_comment/$', 'spa.ajax.mix_add_comment', name='mix_add_comment'),
            url(r'^mix/comments/(?P<mix_id>\d+)/$', 'spa.ajax.mix_comments', name='ajax_mix_comments'),
            url(r'^header/$', 'spa.ajax.header', name='header'),
            url(r'^session_play_count/$', 'spa.ajax.session_play_count'),
            url(r'^mix_stream_url/(?P<mix_id>\d+)/$', 'spa.ajax.get_mix_stream_url'),
            url(r'^release_player/(?P<release_id>\d+)/$', 'spa.ajax.release_player'),
            url(r'^live_now_playing/$', 'spa.ajax.live_now_playing'),
            url(r'^mark_read/$', 'spa.ajax.mark_read'),
            url(r'^facebook_post_likes_allowed/$', 'spa.ajax.facebook_post_likes_allowed',
                name='ajax_facebook_post_likes_allowed'),
            url(r'^upload_mix_image/(?P<mix_id>\d+)/$', 'spa.ajax.upload_mix_image', name='ajax_upload_mix_image'),
            url(r'^upload_release_image/(?P<release_id>\d+)/$', 'spa.ajax.upload_release_image',
                name='ajax_upload_release_image'),
            url(r'^upload_avatar_image/$', 'spa.ajax.upload_avatar_image', name='ajax_upload_avatar_image'),
            url(r'^lookup/search/$', 'spa.ajax.lookup_search', name='ajax_lookup'),
            url(r'^lookup/(?P<source>\w+)/$', 'spa.ajax.lookup', name='ajax_lookup'),
        ]
        return pattern_list


def _get_json(payload, key='value'):
    data = {
    key: payload
    }
    return simplejson.dumps(data)


@render_to('inc/header.html')
def header(request):
    return HttpResponse(render_to_response('inc/header.html'))


def session_play_count(request):
    """

    :param request:
    :return: Number of tracks played in this session
    """
    if not request.user.is_authenticated():
        if 'play_count' in request.session:
            result = simplejson.dumps({
            'play_count': request.session['play_count']
            })
        else:
            result = simplejson.dumps({
            'play_count': '0'
            })
    else:
        result = simplejson.dumps({
        'play_count': '0'
        })
    return HttpResponse(result, mimetype='application/json')


def get_mix_stream_url(request, mix_id):
    try:
        if not request.user.is_authenticated():
            if 'play_count' in request.session:
                request.session['play_count'] += 1
            else:
                request.session['play_count'] = 1

        mix = Mix.objects.get(pk=mix_id)
        mix.add_play(request.user)
        data = {
            'stream_url': mix.get_stream_path(),
            'description': mix.description,
            'item_url': mix.get_absolute_url(),
            'title': mix.title
        }
        return HttpResponse(simplejson.dumps(data), mimetype="application/json")
    except Exception, e:
        logger.exception("Error getting mix stream url")
        raise #HttpResponse("Error getting mix stream url", status=401)


def live_now_playing(request):
    now_playing_info = live.get_now_playing(
        localsettings.JS_SETTINGS['LIVE_STREAM_URL'],
        localsettings.JS_SETTINGS['LIVE_STREAM_PORT'],
        localsettings.JS_SETTINGS['LIVE_STREAM_MOUNT'])
    try:
        if now_playing_info is not None:
            return HttpResponse(
                simplejson.dumps({
                'stream_url': 'http://%s:%s/%s' % (
                localsettings.JS_SETTINGS['LIVE_STREAM_URL'],
                localsettings.JS_SETTINGS['LIVE_STREAM_PORT'],
                localsettings.JS_SETTINGS['LIVE_STREAM_MOUNT']),
                'description': now_playing_info['stream_description'],
                'title': now_playing_info['current_song']
                }), mimetype="application/json")
    except:
        return HttpResponseNotFound(now_playing_info)

    return None


@render_to('inc/release_player.html')
def release_player(request, release_id):
    return HttpResponse('Hello Sailor')


def mix_add_comment(request):
    if request.POST:
        comment = Comment()
        comment.mix_id = request.POST['mixid']
        comment.user = request.user
        comment.comment = request.POST['comment']
        comment.time_index = request.POST['position']
        comment.save()

        return HttpResponse(_get_json('Comment posted', 'description'))
    else:
        return HttpResponse(_get_json('Error posting', 'description'))


@render_to('inc/comment_list.html')
def mix_comments(request, mix_id):
    return {
    "results": Comment.objects.filter(mix_id=mix_id),
    }


@login_required
def mark_read(request):
    profile = request.user.get_profile()
    if profile is not None:
        Notification.objects.filter(to_user=profile).update(accepted_date=datetime.now())
        return HttpResponse('Success', status=200)
        pass

    return HttpResponse('Unauthorized', status=401)


@login_required()
def facebook_post_likes_allowed(request):
    profile = request.user.get_profile()
    if profile is not None:
        likes_allowed = profile.activity_sharing & UserProfile.ACTIVITY_SHARE_LIKES
        facebook_allowed = profile.activity_sharing_networks & UserProfile.ACTIVITY_SHARE_NETWORK_FACEBOOK

        return HttpResponse(_get_json(bool(likes_allowed & facebook_allowed)), mimetype="application/json")

    return HttpResponse(_get_json(False), mimetype="application/json")


@csrf_exempt
def upload_release_image(request, release_id):
    try:
        if 'release_image' in request.FILES and release_id is not None:
            release = Release.objects.get(pk=release_id)
            if release is not None:
                release.release_image = request.FILES['release_image']
                release.save()
                return HttpResponse(_get_json("Success"))
    except Exception, ex:
        logger.exception("Error uploading release image")
    return HttpResponse(_get_json("Failed"))


def upload_mix_image(request, mix_id):
    try:
        if len(request.FILES) != 0:
            mix = Mix.objects.get(pk=mix_id)
            if mix:
                mix.mix_image = request.FILES[request.FILES.keys()[0]]
                mix.save()
                return HttpResponse(json.dumps({'status': 'OK', 'url': mix.get_image_url()}))
    except Exception, ex:
        logger.exception("Error uploading avatar: %s", ex.message)
        return HttpResponse(json.dumps({'status': 'failed', 'message': ex.message}))

    return HttpResponse(json.dumps({'status': 'failed', 'message': 'No image file found'}))


def upload_avatar_image(request):
    # TODO: fergal.moran@gmail.com
    # Problem here that only the current user can update avatar
    # Might need to allow staff to change other's avatars?
    try:
        if len(request.FILES) != 0:
            profile = request.user.get_profile()
            if profile:
                profile.avatar_image = request.FILES[request.FILES.keys()[0]]
                profile.avatar_type = 'custom'
                profile.save()
                return HttpResponse(json.dumps({'status': 'OK', 'url': profile.get_avatar_image()}))
    except Exception, ex:
        logger.exception("Error uploading avatar: %s", ex.message)
        return HttpResponse(json.dumps({'status': 'failed', 'message': ex.message}))

    return HttpResponse(json.dumps({'status': 'failed', 'message': 'No image file found'}))


@require_POST
@login_required
@csrf_protect
def upload(request):
    # The assumption here is that jQuery File Upload
    # has been configured to send files one at a time.
    # If multiple files can be uploaded simultaneously,
    # 'file' may be a list of files.
    try:
        uid = request.POST['upload-hash']
        in_file = request.FILES['file'] if request.FILES else None
        file_name, extension = os.path.splitext(in_file.name)

        file_storage = FileSystemStorage(location=os.path.join(settings.CACHE_ROOT, "mixes"))
        cache_file = file_storage.save("%s%s" % (uid, extension), ContentFile(in_file.read()))
        response = ''

        try:
            create_waveform_task.delay(in_file=os.path.join(file_storage.base_location, cache_file), uid=uid)
        except:
            logger.debug("Unable to connect to celery")
            response = 'Unable to connect to waveform generation task, there may be a delay in getting your mix online'

        file_dict = {
            'response': response,
            'size': in_file.size,
            'uid': uid
        }

        return UploadResponse(request, file_dict)
    except Exception, ex:
        logger.exception(ex.message)
        raise


@csrf_exempt
def lookup_search(request):
    query = request.GET['query'] if 'query' in request.GET else request.GET['q'] if 'q' in request.GET else ''
    if query != '':
        filter_field = Mix.get_lookup_filter_field()
        kwargs = {
        '{0}__{1}'.format(filter_field, 'icontains'): query,
        }
        rows = Mix.objects.values("title").filter(**kwargs)
        #results = serializers.serialize("json", rows, fields="title",)
        results = json.dumps(rows)
        return HttpResponse(results, mimetype='application/json')


@csrf_exempt
def lookup(request, source):
    query = request.GET['query'] if 'query' in request.GET else request.GET['q'] if 'q' in request.GET else ''
    if query != '':
        model = get_model('spa', source)
        if model is not None:
            filter_field = model.get_lookup_filter_field()
            kwargs = {
            '{0}__{1}'.format(filter_field, 'icontains'): query,
            }
            rows = model.objects.filter(**kwargs)
            results = json.to_ajax(rows, filter_field)
            return HttpResponse(simplejson.dumps(results), mimetype='application/json')
    return HttpResponse(_get_json("Key failure in lookup"), mimetype='application/json')
