# -*- coding: utf-8 -*-
from flask import request
from crestify import api, redis, hashids
from flask_restful import Resource, reqparse
from crestify.models import Bookmark, User, Tag, db
from crestify.services import bookmark
from crestify.tasks import bookmark_tasks
from functools import wraps
import shortuuid
import urllib
import urlparse
import arrow
from flask_security import utils as security_utils

parser = reqparse.RequestParser()
parser.add_argument('url', type=str)
parser.add_argument('email', type=str)
parser.add_argument('apikey', type=str)
parser.add_argument('title', type=str)
parser.add_argument('addedon', type=int)  # Send in milliseconds since epoch only
parser.add_argument('tags', type=str)  # Send comma separated string
parser.add_argument('id', type=str)
parser.add_argument('tabs', location='json')
parser.add_argument('password', type=str)


def require_auth(view_function):
    @wraps(view_function)
    def decorated_function(*args, **kwargs):
        args = parser.parse_args()
        query = User.query.filter_by(email=urllib.unquote(args['email']),
                                     api_key=urllib.unquote(args['apikey'])).first()
        if query is not None:
            userid = query.id
            return view_function(userid, args)
        else:
            return {'message': 'Authentication failed'}, 401

    return decorated_function


def require_json(view_function):
    @wraps(view_function)
    def decorated_function(*args, **kwargs):
        print request.json
        print "request data", request.data
        if not request.get_json():
            return {'message': 'JSON Expected.'}, 500
        else:
            return view_function()

    return decorated_function


class CheckURL(Resource):
    method_decorators = [require_auth]

    def post(self, userid, args):
        if args['url'] is not None:
            parsed_url = urlparse.urlparse(urllib.unquote(args['url']))
            url_scheme = "{}://".format(parsed_url.scheme)
            parsed_url = parsed_url.geturl().replace(url_scheme, '', 1)
            query = Bookmark.query.filter(Bookmark.main_url.endswith(parsed_url), Bookmark.user == userid,
                                          Bookmark.deleted == False).order_by(Bookmark.added_on.desc()).first()
            if query:
                return {'message': 'You have this URL bookmarked', 'added': arrow.get(query.added_on).humanize(),
                        'timestamp': arrow.get(query.added_on).strftime("%Y-%m-%dT%H:%M:%SZ"),
                        'id': hashids.encode(query.id)}, 200
            else:
                return {'message': 'You do not have this URL bookmarked'}, 404


class CheckURLInfo(Resource):
    method_decorators = [require_auth]

    def post(self, userid, args):
        if args['url'] is not None:
            parsed_url = urlparse.urlparse(args['url'])
            url_scheme = "{}://".format(parsed_url.scheme)
            parsed_url = parsed_url.geturl().replace(url_scheme, '', 1)
            query = Bookmark.query.filter(Bookmark.main_url.endswith(parsed_url), Bookmark.user == userid,
                                          Bookmark.deleted == False).order_by(Bookmark.added_on.desc()).first()
            if query:
                current_tags = None
                if query.tags:
                    current_tags = ','.join(query.tags)
                user_tags = Tag.query.filter(Tag.user == userid, Tag.count > 0).all()
                user_tags.sort(key=lambda k: k.text.lower())
                [user_tags.remove(tag) for tag in user_tags if tag.text == '']
                if user_tags:
                    user_tags = ','.join([tag.text for tag in user_tags])
                return {'message': 'You have this URL bookmarked', 'tags': current_tags, 'tagopts': user_tags,
                        'id': hashids.encode(query.id)}, 200
            else:
                return {'message': 'You do not have this URL bookmarked'}, 404


class AddURL(Resource):
    method_decorators = [require_auth]

    def post(self, userid, args):
        if args['addedon']:
            added = args[
                        'addedon'] / 1000  # Convert timestamp from milliseconds since epoch to seconds(Chrome sends millisecs)
            new_bookmark = bookmark.new(title=urllib.unquote(args['title']), url=urllib.unquote(args['url']),
                                        user_id=userid, tags=args['tags'])
        else:
            new_bookmark = bookmark.new(title=urllib.unquote(args['title']), url=urllib.unquote(args['url']),
                                        user_id=userid)
        bookmark_tasks.readable_extract.delay(new_bookmark)
        bookmark_tasks.fulltext_extract.delay(new_bookmark)
        bookmark_tasks.fetch_description.delay(new_bookmark)
        return {'message': 'URL bookmarked', 'id': hashids.encode(new_bookmark.id)}, 200


class EditBookmark(Resource):
    method_decorators = [require_auth]

    def post(self, userid, args):
        if args['id']:
            id = hashids.decode(args['id'])[0]
            tags = urllib.unquote(args['tags'])
            tags = tags.split(',')
            edit_bookmark = bookmark.api_edit(id=id,
                                              tags=tags,
                                              user_id=userid)
        else:
            return {'message': 'No ID Supplied'}, 404
        return {'message': 'Bookmark Modified'}, 200


class CheckAuth(Resource):
    def post(self):
        args = parser.parse_args()
        user = User.query.filter_by(email=urllib.unquote(args['email']), api_key=urllib.unquote(args['apikey'])).first()
        if user is not None:
            return {'message': 'Authenticated Successfully'}, 200
        else:
            return {'message': 'Authentication Failed'}, 401


class CheckPassword(Resource):
    def post(self):
        args = parser.parse_args()
        email = args['email']
        password = args['password']
        if email is None or password is None:
            return {'message': "Email or password empty"}, 401
        user = User.query.filter_by(email=args["email"]).first()
        if security_utils.verify_password(password, user.password):
            return {'message': 'Login Successful', 'apikey': user.api_key}, 200
        return {'message': 'Login Failed'}, 401


class DeleteBookmark(Resource):
    method_decorators = [require_auth]

    def post(self, userid, args):
        if args['id']:
            id = hashids.decode(args['id'])[0]
            delete_bookmark = bookmark.delete(id=id, user_id=userid)
        else:
            return {'message': 'No ID Supplied'}, 404
        return {'message': 'Bookmark Deleted'}, 200


class AddTabs(Resource):
    method_decorators = [require_auth]

    def post(self, userid, args):
        if args['tabs']:
            print type(args['tabs'])
            uuid = shortuuid.uuid()
            r = redis.set(uuid, urllib.unquote(args['tabs']))
            #  Expire Redis key in 10 minutes
            redis.expire(uuid, 600)
            return {'id': uuid}


api.add_resource(CheckURL, '/api/check')
api.add_resource(AddURL, '/api/add')
api.add_resource(CheckAuth, '/api/authenticate')
api.add_resource(CheckURLInfo, '/api/checkinfo')
api.add_resource(EditBookmark, '/api/edit')
api.add_resource(DeleteBookmark, '/api/delete')
api.add_resource(AddTabs, '/api/tabs/add')
api.add_resource(CheckPassword, '/api/login')