"""
    This file consists in managing all things user related
"""
from utils.transport import CouchdbReader, CouchdbWriter
from threading import Thread
import json
class User :
    def __init__(self,**args) :
        """
            @param product  identifier of the product we are working with
            @param stripe   stripe handler
            @param store    transport store (couchdb, ...)
        """
        self.stripe = args["stripe"]
        self.store = args['store']
        
        self.store['dbname'] = str(args['product'])
        self.product = str(args['product'])
        
        self.me = {}
        self.init()

    def init(self):
        lproducts = self.stripe.Product.list()
        lproducts = [item for item in lproducts.auto_paging_iter() if item.name == self.product ]
        if lproducts :
            self.me['info'] = {"active":lproducts[0].active,"id":lproducts[0].id,"description":lproducts[0].statement_descriptor,"images":lproducts[0].images}
            self.plans = self.stripe.Plan.list(product=lproducts[0].id)
            self.plans = [item for item in self.plans.auto_paging_iter() ]

    def init_customer(self,uid,pid):
        """
            This function copies a customer to the internal database.
            This would allow the object to be in sync with what is available in stripe and we will save the content later on ...
        """
        customer = self.stripe.Customer.list(email=uid)
        if customer :
            customer = [item for item in customer if item.email == uid]
            customer = customer[0]
            
            #
            # Insure the product is the one we are looking for ...
            args = dict(self.store)  
            args['uid']=uid
            reader = CouchdbReader(**args)
            key = reader.view('users/uid_map',key=uid)        
            if not key :
                self.store['uid'] = customer.id
                self.update(_id=customer.id,emails=[uid])
                #
                # We need to update the user's subscription
                #
                product_id = self.me['info']['id']
                info = {}
                lsub = customer.subscriptions ;
                
                info = {}
                found = False
                for sub in lsub.data :                    
                    if sub.plan.id == pid or sub.plan.product == product_id:
                        info[sub.plan.nickname] = sub.plan
                self.update(subscriptions=info)
                self.post()
            #-- housekeeping work
            else:
                #
                # The key exists we need to just read the user info in me
                reader.uid = key
                document = reader.read()                
                self.me = dict(self.me,**document)
            self.user_key = customer.id
	    return customer
        else:
            return None

    

    def update(self,**args):
        for key in args :
            value = args[key]
            if key in self.me :
                if not isinstance(self.me[key],dict) or not isinstance(value,dict) :
                    if not isinstance(self.me[key],list) :
                        self.me[key] = [self.me[key],value]
                    elif isinstance(self.me[key],list):
                        self.me[key] += value if  isinstance(value,list) else [value]
                else:
                    self.me[key] = dict(self.me[key],**value)
            else:
                self.me[key] = value
         
    def post(self,**args):
        document = dict(self.me,**{})
        
        args = dict(self.store)
        args['create'] = True
        
        writer = CouchdbWriter(**args)
        writer.set(document)
        
        # writer.close()
    def get_key(self,uid):
        reader = CouchdbReader(**self.store)
        key = reader.view('users/uid_map',key=uid)
        
        if key :
            if isinstance(key,list) :
                key = key[0]['value']
            elif 'value' in key :
                key = key['value']
        else:
            key = None
        return key
    def get(self,uid,key):
        args = dict(self.store)
        args['uid'] = self.get_key(uid)
        if key not in self.me :
            couchdb = CouchdbReader(**args)
            document = couchdb.basic_read()        
            return document[key] if key in document else {}
        else:
            return self.me[key]
    # def plans(self,free=False):
    #     lproducts = self.stripe.Product.list()
    #     plans = [item for item in lproducts.auto_paging_iter() if item.name == self.product ]
    #     if free == True :
    #         plans = [item for item in plans if item.amount == 0]
    #     return plans
    def subscribe(self,uid,pid=None,stripeToken=None) :
        """
            @param uid          user's email
            @param pid          plan id
            @param stripeToken  stripe token to process payments
        """
        customer = self.init_customer(uid,pid)
        product_id = self.me['info']['id']
        if pid is None :
            #
            # In this block we try to find the free plan if one isn't specified
            # The informtion about the product is already known (constructor)
            #
            plans = [item for item in self.plans if item.amount == 0]
            pid = None if not plans else plans[0].id
        
        if not customer :
            customer = self.stripe.Customer.create(email=uid)
            self.update(_id=customer.id,emails=[uid])
        elif not self.me['subscriptions']:
            #
            # We have a customer and subscription information that goes with it
            # 
            mysub = {"plans":[]}
            for rows in customer.subscriptions.data :
                lsub = rows.items()
                myplans = [ item[1]for item in lsub if 'plan' in item and item[1]['product'] == self.me['info']['id'] and item[1]['active'] ]
                if myplans :
                    for plan in myplans :
                        plan['metadata'] = str(plan['metadata'])
                        
                        self.me['subscriptions'] = {plan['nickname']: dict(plan)}
                    
                
            
            # print customer.subscriptions.data[0].items()]
            # self.post(uid=customer.id)
            
            
            
        # else:
        #     customer = customer
        self.store['uid'] = customer.id
        args = {"customer":customer.id,"items":[{"plan":pid}]}        
        if stripeToken:
            args['source'] = stripeToken
        
        sub = self.me['subscriptions']
        found = len([1 for plan_key in sub if sub[plan_key]['id'] == pid]) > 0
        if found is False :
            sub = self.stripe.Subscription.create(**args)            
            info = {sub.plan.nickname:sub.plan}
            self.update(subscriptions=info)

        self.post(uid=customer.id) 
        #
        # keep a copy of this on our servers ...
        #
        
    def refresh(self,uid):
        parent = (self)
        def _update(customer_id) :
            
            customer = parent.stripe.Customer.retrieve(customer_id)
            parent.store['uid'] = customer.id
            lsub    = customer.subscriptions
            reader  = CouchdbReader(**parent.store)
            _me     = reader.read()
            if 'emails' not in parent.me :
                parent.me['emails'] = []
            emails = list(set(parent.me['emails']) | set(_me['emails']))
            parent.me = dict(parent.me,**_me)
            parent.me['emails'] = emails
            
            product_id = parent.me['info']['id']            
            [parent.update(subscriptions={sub.plan.nickname:sub.plan}) for sub in lsub.auto_paging_iter() if sub.plan.product  == product_id and sub.plan.active == True]            
            
            parent.post()
        key = self.get_key(uid)
        # reader = CouchdbReader(**self.store)
        # key = reader.view('users/uid_map',key=uid)
        
        # if key :
        #     if isinstance(key,list) :
        #         key = key[0]['value']
        #     elif 'value' in key :
        #         key = key['value']
        if key :
            thread = Thread(target=_update,args=(key,))
            thread.start()
        
        # thread.start()
        
    def pay(self,uid,pid,stripeToken):
        pass   

