#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import time
from copy import deepcopy
from datetime import datetime, timedelta

from openid.store import nonce
from openid.association import Association

from ming.orm import FieldProperty
from ming.orm.declarative import MappedClass
from .session import main_doc_session, main_orm_session
from .session import project_doc_session, project_orm_session

class OpenIdAssociation(MappedClass):
    class __mongometa__:
        name='oid_store_assoc'
        session = main_orm_session

    _id = FieldProperty(str) # server url
    assocs = FieldProperty([dict(
                key=str, value=str)])

    # Mimic openid.store.memstore.ServerAssocs
    def set_assoc(self, assoc):
        for a in self.assocs:
            if a['key'] == assoc.handle:
                a['value'] = assoc.serialize()
                return
        self.assocs.append(dict(key=assoc.handle, value=assoc.serialize()))

    def get_assoc(self, handle):
        for a in self.assocs:
            if a['key'] == handle:
                return Association.deserialize(a['value'])
        return None

    def remove_assoc(self, handle):
        old_len = len(self.assocs)
        self.assocs = [
            a for a in self.assocs
            if a['key'] != handle ]
        return old_len != len(self.assocs)

    def best_assoc(self):
        best = None
        for assoc in self.assocs:
            assoc = Association.deserialize(assoc['value'])
            if best is None or best.issued < assoc.issued:
                best = assoc
        if best:
            return best
        else:
            return None

    def cleanup_assocs(self):
        old_len = len(self.assocs)
        self.assocs = [ a for a in self.assocs
                        if Association.deserialize(a['value']).getExpiresIn() != 0 ]
        new_len = len(self.assocs)
        return (old_len - new_len), new_len

class OpenIdNonce(MappedClass):
    class __mongometa__:
        name='oid_store_nonce'
        session = main_orm_session

    _id = FieldProperty(str) # Nonce value
    timestamp = FieldProperty(datetime, if_missing=datetime.utcnow)
        
class OpenIdStore(object):

    def _get_assocs(self, server_url):
        assoc = OpenIdAssociation.query.get(_id=server_url)
        if assoc is None:
            assoc = OpenIdAssociation(_id=server_url)
        return assoc
    
    def storeAssociation(self, server_url, association):
        assocs = self._get_assocs(server_url)
        assocs.set_assoc(deepcopy(association))

    def getAssociation(self, server_url, handle=None):
        assocs = self._get_assocs(server_url)
        if handle is None:
            return assocs.best_assoc()
        else:
            return assocs.get_assoc(handle)

    def removeAssociation(self, server_url, handle):
        assocs = self._get_assocs(server_url)
        return assocs.remove_assoc(handle)

    def useNonce(self, server_url, timestamp, salt):
        if abs(timestamp - time.time()) > nonce.SKEW:
            return False
        key = str((server_url, timestamp, salt))
        if OpenIdNonce.query.get(_id=key) is None:
            OpenIdNonce(_id=key)
            return True
        else:
            return False

    def cleanupNonces(self):
        now = datetime.utcnow()
        cutoff = now - timedelta(seconds=nonce.SKEW)
        num_removed = OpenIdNonce.query.remove(dict(
                timestamp={'$lt': cutoff}))
        return num_removed

