import pywikibot as p
import datetime as t

site = p.Site('wikidata', 'wikidata')
repo = site.data_repository()

now = t.datetime.now()
def getClaims(item, prop):
    Qitem = p.ItemPage(repo, item)
    Qitem.get()
    if Qitem.claims:
        if prop in Qitem.claims.keys():
            return Qitem.claims[prop]
        else:
            print('getClaims: Missing claim ', prop, ' in item ', item)
    else:
        print('getClaims: Item ', item, 'has no claims')
        
    return False   
def retrieveDatabaseProperties(databaseItem):
    dbItem = p.ItemPage(repo, databaseItem)
    dbItem.get()
    if dbItem.claims: # database item has any claim
        if 'P1687' in dbItem.claims.keys(): # database item has at least one "Wikidata property" claim
            wdDBProps = dbItem.claims['P1687']
            if len(wdDBProps) == 1: # database item has exactly one "Wikidata property" claim
                wdDBProp = wdDBProps[0]
            else:
                print('retrieveDatabaseProperties: Found ', len(wdDBProps), ' database properties, expect 1')
                return False
        else:
            print('retrieveDatabaseProperties: Missing claim P1687 in database item ', databaseItem)
            return False
        if 'P407' in dbItem.claims.keys(): # database item has at least "language" claim
            wdDBLangs = dbItem.claims['P407']
            if len(wdDBLangs) == 1: # database item has exactly one "language" claim
                wdDBLang = wdDBLangs[0]
                langItem = p.ItemPage(repo, wdDBLang.target.id)
                langItem.get()
                if langItem.claims: # language item has claims
                    if 'P305' in langItem.claims.keys(): # language item has at lease one relevant language code claim
                        langItemLangCodes = langItem.claims['P305']
                        if len(langItemLangCodes) == 1: # language item has exactly one language code claim
                            langItemLangCode = langItemLangCodes[0]
                        else:
                            print('retrieveDatabaseProperties: Found ', len(langItemLangCodes), ' language codes, expect 1')
                            return False
                    else:
                        print('retrieveDatabaseProperties: Missing claim P305 in language item ', wdDBLang.target.id)
                        return False
                else:
                    print('retrieveDatabaseProperties: Language item ', wdDBLang.target.id, 'has no claims')
                    return False
            else:
                print('retrieveDatabaseProperties: Found ', len(wdDBLangs), ' language claims, expect 1')
                return False
        else:
            print('retrieveDatabaseProperties: Missing claim P407 in database item ', databaseItem)
            return False
    else:
        print('retrieveDatabaseProperties: Database item ', databaseItem, 'has no claims')
        return False
    
    return {'databaseProperty' : wdDBProp.target['id'], 'databaseLanguageCode' : langItemLangCode.target} # a dictionary
def makeDatabaseSource(databaseItem, externalId, externalTitle, retDate={'year':now.year,'month':now.month,'day':now.day}):
    dbProps = retrieveDatabaseProperties(databaseItem)
    if dbProps == False: # database item is not suitable right now; fix it or don't use this property for sources
        print('makeDatabaseSource: Could not retrieve database properties')
        return False
    
    statedin = p.Claim(repo, 'P248')
    statedin.setTarget(value=p.ItemPage(repo, databaseItem))
    extId = p.Claim(repo, dbProps['databaseProperty'])
    extId.setTarget(value=externalId)
    extTitle = p.Claim(repo, 'P1476')
    extTitle.setTarget(value=p.WbMonolingualText(text=externalTitle, language=dbProps['databaseLanguageCode']))
    retrieved = p.Claim(repo, 'P813')
    retrieved.setTarget(value=p.WbTime(year=retDate['year'], month=retDate['month'], day=retDate['day']))

    return [statedin, extId, extTitle, retrieved] # a list containing claim objects
def makeWorldRowingSource(externalId, externalTitle, retDate={'year':now.year,'month':now.month,'day':now.day}):
    return makeDatabaseSource('Q21008628', externalId, externalTitle, retDate) # a list containing claim objects
def makeSportsReferenceSource(externalId, externalTitle, retDate={'year':now.year,'month':now.month,'day':now.day}):
    return makeDatabaseSource('Q18002875', externalId, externalTitle, retDate) # a list containing claim objects
def hasDatabaseSource(claim, sourceProp, sourceValue):
    for source in claim.sources: # all sources of the claim to check
        for sourceClaim in source.items(): # individual claims within that source
            if sourceClaim[0] == sourceProp: # one of the claims has the relevant database property
                relevantClaim = sourceClaim[1][0]
                if len(sourceClaim[1]) == 1:
                    if relevantClaim.target == sourceValue: # the relevant claim has the correct value
                        return True
    return False
def compareValues(claim, value):
    print(vars(claim))
    print(value)
# list of data types: https://www.wikidata.org/wiki/Special:ListDatatypes and https://www.wikidata.org/wiki/Help:Data_type
# unsupported: commonsMedia globe-coordinate wikibase-property math
# supported: wikibase-item string monolingualtext quantity time url external-id
    if claim._type == 'wikibase-item': # value cames as Qid (string)
        return claim.target.id == value
    elif claim._type == 'string':
        return claim.target == value
    elif claim._type == 'monolingualtext':
        return False
    elif claim._type == 'quantity':
        return False
    elif claim._type == 'time': # value comes as YYYY-MM-DD
        year = '%04d' %(claim.target.year)
        month = '%02d' %(claim.target.month)
        day = '%02d' %(claim.target.day)
        return year == value[:4] and month == value[5:7] and day == value[8:]
    elif claim._type == 'url': # value comes as plain URL (string)
        return claim.target == value
    elif claim._type == 'external-id': # value comes as string
        return claim.target == value 
    else:
        return False
def processClaim(item, prop, value, sProp, sValue, sTitle, retDate={'year':now.year,'month':now.month,'day':now.day}):
    claims = getClaims(item, prop)
    for claim in claims:
#        print(vars(claim), "\n")
        if compareValues(claim, value):
            hasSource = hasDatabaseSource(claim, sProp, sValue)
            if hasSource == True:
                print(item, ':', prop, ':', value, ' is already sourced with ', sProp, ':', sValue, sep='')
            else:
                if sProp == 'P1447':
                    source = makeSportsReferenceSource(sValue, sTitle, retDate)
                elif sProp == 'P2091':
                    source = makeWorldRowingSource(sValue, sTitle, retDate)
                else:
                    source = False
                if source != False:
#                   claim.addSources(source)
                    print(item, ':', prop, ':', value, ' was not yet sourced with ', sProp , ':', sValue, '; a source was compiled and added:\n', sep='')
                    for sourceClaim in source:
                        print(sourceClaim.id, ': ', sourceClaim.target, sep='')
                else:
                    print(item, ':', prop, ':', value, ' was not yet sourced with ', sProp , ':', sValue, '; was not able to set up a source', sep='')
        else:
            print('Found a different value; no action taken')
#processClaim('Q67660', 'P106', 'Q13382576', 'P1447', 'sc/richard-schmidt-1', 'Richard Schmidt')
#print("\n")
#processClaim('Q67660', 'P106', 'Q13382576', 'P2091', '21891', 'Richard Schmidt', {'year':2015,'month':10,'day':27})
#print("\n")
#processClaim('Q1827786', 'P106', 'Q13382576', 'P2091', '32188', 'Lisa Schmidla')
#print("\n")
#processClaim('Q67660', 'P2091', '21891', 'P2091', '21891', 'Richard Schmidt')
#print("\n")
processClaim('Q20642648', 'P973', 'http://olympic.ca/team-canada/carling-zeeman/', 'P2091', '43082', 'Carling Zeeman')
{'target': 'http://olympic.ca/team-canada/carling-zeeman/', 'id': 'P973', 'isQualifier': False, 'qualifiers': OrderedDict(), 'isReference': False, 'hash': None, '_type': 'url', 'on_item': ItemPage('Q20642648'), 'snak': 'Q20642648$30f64aa4-4e68-a752-07b1-a8803c869f61', 'sources': [], 'snaktype': 'value', 'repo': DataSite("wikidata", "wikidata"), 'rank': 'normal'}
http://olympic.ca/team-canada/carling-zeeman/
Q20642648:P973:http://olympic.ca/team-canada/carling-zeeman/ was not yet sourced with P2091:43082; a source was compiled and added:

P248: [[wikidata:Q21008628]]
P2091: 43082
P1476: {
    "language": "en",
    "text": "Carling Zeeman"
}
P813: {
    "after": 0,
    "before": 0,
    "calendarmodel": "http://www.wikidata.org/entity/Q1985727",
    "precision": 11,
    "time": "+00000002016-11-18T00:00:00Z",
    "timezone": 0
}
{'target': 'http://rowingcanada.org/national-team/athletes/carling-zeeman', 'id': 'P973', 'isQualifier': False, 'qualifiers': OrderedDict(), 'isReference': False, 'hash': None, '_type': 'url', 'on_item': ItemPage('Q20642648'), 'snak': 'Q20642648$4f290d21-4316-e53f-ce1d-822b97bd51eb', 'sources': [], 'snaktype': 'value', 'repo': DataSite("wikidata", "wikidata"), 'rank': 'normal'}
http://olympic.ca/team-canada/carling-zeeman/
Found a different value; no action taken

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-12-3a826750da12> in <module>()
----> 1 outValue = b.testSourceBot(10)
      2 print(outValue)

NameError: name 'b' is not defined