from flask_login import UserMixin
from app.extensions import cache ,bcrypt
import bcrypt as bcr
from .. import db
from ..mixins import CRUDMixin
import datetime
from rauth import OAuth1Service, OAuth2Service
from flask import current_app, url_for, request, redirect, session


class Oauth(CRUDMixin, UserMixin, db.Model):
    __tablename__ = 'oauth'
    id = db.Column(db.Integer, primary_key=True)
    #user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    #oauth = db.relationship("Oauth", back_populates="users")
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    social_id = db.Column(db.String(64), nullable=False, unique=True)
    nickname = db.Column(db.String(64), nullable=True)
    email = db.Column(db.String(64), nullable=True)
    jmeno = db.Column(db.String(128), nullable=False)
    prijmeni = db.Column(db.String(128), nullable=False)
    profile_url = db.Column(db.String(128), nullable=False)
    image_url = db.Column(db.String(128), nullable=False)

class OAuthSignIn(object):
    providers = None

    def __init__(self, provider_name):
        self.provider_name = provider_name
        credentials = current_app.config['OAUTH_CREDENTIALS'][provider_name]
        self.consumer_id = credentials['id']
        self.consumer_secret = credentials['secret']

    def authorize(self):
        pass

    def callback(self):
        pass

    def get_callback_url(self):
        return url_for('public.oauth_callback', provider=self.provider_name,
                       _external=True)

    @classmethod
    def get_provider(self, provider_name):
        if self.providers is None:
            self.providers = {}
            for provider_class in self.__subclasses__():
                provider = provider_class()
                self.providers[provider.provider_name] = provider
        return self.providers[provider_name]

class FacebookSignIn(OAuthSignIn):
    def __init__(self):
        super(FacebookSignIn, self).__init__('facebook')
        self.service = OAuth2Service(
            name='facebook',
            client_id=self.consumer_id,
            client_secret=self.consumer_secret,
            authorize_url='https://graph.facebook.com/oauth/authorize',
            access_token_url='https://graph.facebook.com/oauth/access_token',
            base_url='https://graph.facebook.com/'
        )

    def authorize(self):
        return redirect(self.service.get_authorize_url(
            scope='email',
            response_type='code',
            redirect_uri=self.get_callback_url())
        )

    def callback(self):
        if 'code' not in request.args:
            return None, None, None, None, None, None, None
        oauth_session = self.service.get_auth_session(
            data={'code': request.args['code'],
                  'grant_type': 'authorization_code',
                  'redirect_uri': self.get_callback_url()}
        )
        me = oauth_session.get('me?fields=id,email,name').json()
        profile_url = "http://facebook.com/profile.php?id=%s" % me['id']
        image_url = "http://graph.facebook.com/%s/picture" % me['id']
        return (
            'facebook$' + me['id'],
            me.get('email').split('@')[0] if me.get('email') is not None else "anon"+me['id'],
            me.get('email'),
            me['name'].split(' ')[0],
            me['name'].split(' ')[1],
            profile_url,
            image_url
        )

class TwitterSignIn(OAuthSignIn):
    def __init__(self):
        super(TwitterSignIn, self).__init__('twitter')
        self.service = OAuth1Service(
            name='twitter',
            consumer_key=self.consumer_id,
            consumer_secret=self.consumer_secret,
            request_token_url='https://api.twitter.com/oauth/request_token',
            authorize_url='https://api.twitter.com/oauth/authorize',
            access_token_url='https://api.twitter.com/oauth/access_token',
            base_url='https://api.twitter.com/1.1/'
        )

    def authorize(self):
        request_token = self.service.get_request_token(
            params={'oauth_callback': self.get_callback_url()}
        )
        session['request_token'] = request_token
        return redirect(self.service.get_authorize_url(request_token[0]))

    def callback(self):
        request_token = session.pop('request_token')
        if 'oauth_verifier' not in request.args:
            return None, None, None, None, None, None, None
        oauth_session = self.service.get_auth_session(
            request_token[0],
            request_token[1],
            data={'oauth_verifier': request.args['oauth_verifier']}
        )
        me = oauth_session.get('account/verify_credentials.json').json()
        social_id = 'twitter$' + str(me.get('id'))
        username = me.get('screen_name')
        name = me.get('name').split(' ')
        return (
            social_id,
            username,
            None,
            name[0],
            name[1] if name.__len__()>1 else '',
            #'@%s' % me.get('screen_name') - display name (@Atheloses)
            "http://twitter.com/%s" % me.get('screen_name'),
            me.get('profile_image_url')
        )