#!/usr/bin/python3
import requests
import datetime
from tabulate import tabulate
import boto3
import json
from json import JSONEncoder
import logging
from zoneinfo import ZoneInfo
logging.basicConfig(level=logging.INFO)
class libaccount(dict):
    def __init__(self,name,barcode,pin):
        dict.__init__(self,name=name, barcode=barcode, pin=pin)
        self.name=name
        self.barcode=barcode
        self.pin=pin
    def toJson(self):
        return json.dumps(self,default=lambda o: o.__dict__)
class book():
    def __init__(self,itemid,renewalcount,checkoutdate,duedate,vendor,resourceid,title,materialtype,coverurl,person,authsession,renewresult,overdue,isbn):
        self.id=itemid
        self.renewalcount=renewalcount
        self.checkoutdate=checkoutdate
        self.duedate=duedate
        self.vendor=vendor
        self.resourceid=resourceid
        self.title=title
        self.materialtype=materialtype
        self.coverurl=coverurl
        self.person=person
        self.authsession=authsession
        self.renewresult=renewresult
        self.overdue=overdue
        self.isbn=isbn
        #self.ill=ill
    def print(self):
        print(self.person, self.id, self.title, self.checkoutdate, self.renewalcount, self.duedate, self.materialtype,self.renewresult, self.isbn)
    def renew(self):
        try:
            logging.info("Renewing Book",self.title)
            renewuri='https://na2.iiivega.com/api/search-result/patrons/me/checkouts/' + self.id + '/renew'
            try:
                renewresult = self.authsession.post(renewuri).json()
                if renewresult.get('message'):
                    self.renewresult=renewresult['message']
                else:
                    self.renewalcount=renewresult['renewalCount']
                    self.duedate=renewresult['dueDate']
                    self.renewresult="Successfully Renewed"
            except requests.exceptions.RequestException as e:  # This is the correct syntax
                logging.error(e.json())
            finally:
                pass
                #print(renewresult.json())
        except Exception as ex:
            logging.error(ex)
def sendemail(body,subject):
    logging.info("Sending Email")
    boto3.setup_default_session(profile_name='default')
    sesclient=boto3.client('ses',region_name="us-east-2")
    CHARSET="UTF-8"
    response = sesclient.send_email(
        Destination={
            "ToAddresses":recipients
        },
        Message= {
            "Body": {
                "Html": {
                    "Charset": CHARSET,
                    "Data": body
                }
            },
            "Subject": {
                "Charset": CHARSET,
                "Data": subject
            },
        },
        Source='librarynotices@hamik.net'
    )
upcomingdays=5
autorenewaldays=3
alwayssendemail=False
returndata=False
recipients=['dan@hamik.net','allisonmhamik@gmail.com','danalli@hamik.net','henryhamik@gmail.com','charleyhamik@gmail.com']
uri = "https://auth.na2.iiivega.com/auth/realms/sioux/protocol/openid-connect/token"
checkoutsuri='https://sioux.na2.iiivega.com/api/search-result/patrons/me/checkouts'
with open('/var/www/data/libaccounts.json') as accountfile:
   accountsjson= json.load(accountfile)
   
accounts=[]
for account in accountsjson:
    accounts.append(
        libaccount(
            accountsjson[account]['name'],
            str(accountsjson[account]['barcode']),
            str(accountsjson[account]['pin']))
        )

allbooks=[]
mediatypes=[]
for myaccount in accounts:
    account=myaccount
    logging.info(account['name'])
    # Create a session
    session = requests.Session()
    authbody = {
        'username':account.barcode,
        'password':account.pin,
        'client_id':'convergence',
        'grant_type':'password',
    }
    resp=session.post(uri,authbody).json()
    authtoken=resp['access_token']
    tokentype=resp['token_type']
    sessionstate=resp['session_state']
    
    session.headers.update({
        'iii-customer-domain':'sioux.na2.iiivega.com',
        'Origin':'https://sioux.na2.iiivega.com/',
        'Referrer':'https://sioux.na2.iiivega.com/',
        'access_token':authtoken,
        'Authorization':'Bearer ' + authtoken,
        'token_type': tokentype,
        'session_state': sessionstate,
        'api-version':'1',
        'DNT':'1',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
           } )
    outs = session.get(checkoutsuri)
    if len(outs.json()) >=1:
        for mybook in outs.json():
            if mybook['vendor']=='overdrive':
                continue
            if mybook['vendor']=='hoopla':
                continue
            try:
                myisbn = mybook['resource']['coverUrl']['small'].split('=')[1].split("/")[0]
            except:
                myisbn='' 
            try:
                mycoverurl = mybook['resource']['coverUrl']['small']
            except:
                mycoverurl = ''
            duedate = datetime.datetime.strptime(mybook['dueDate'].split('T')[0],'%Y-%m-%d').date()
            if datetime.date.today() > duedate:
                overdue=True
            else:
                overdue = False
            try:
                thisbook = book(
                    mybook['id'],
                    mybook['renewalCount'],
                    datetime.datetime.strptime(mybook['checkOutDate'].split('T')[0],'%Y-%m-%d').date(),
                    duedate,
                    mybook['vendor'],
                    mybook['resource']['id'],
                    mybook['resource']['title'],
                    mybook['resource']['materialType'],
                    mycoverurl,
                    account.name,
                    session,
                    'None',
                    overdue,
                    myisbn
                    )
                if thisbook.materialtype in mediatypes:
                    pass
                else:
                    mediatypes.append(thisbook.materialtype)
            except Exception as e:
                print(e,mybook)
            allbooks.append(thisbook)
for book in allbooks:
    #print(datetime.date.today(),book.duedate)
    if datetime.date.today() > book.duedate:
        book.renew()
        
#sendemail()
tablestart="""
<!DOCTYPE html PUBLIC "-=//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns=3D"http://www.w3.org/1999/xhtml"> 
<head> </head>
<body>
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style><table>"""
tableend="</table> </body></html>"
timezone = ZoneInfo("America/Chicago")
returntable="Last Updated" + str(datetime.datetime.now(timezone)) 
returntable+='<br>Click <a href="https://librarynotice.hamik.net">Here</a> to visit the site.'
returntable += """<form action="https://librarynotice.hamik.net/refresh.php">
<input type="submit" value="Refresh Items">
</form>
"""

#print(htmltable)
td="</td><td>"
th="</th><th>"
#returntable = '<a href="https://librarynotice.hamik.net">Click to return to main list</a>' 
duesoon = [d for d in allbooks if (d.duedate < datetime.date.today() + datetime.timedelta(days=10)) and not (str(d.renewresult).lower() == 'None'.lower())]
if len(duesoon) >=1:
    returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
    for type in mediatypes:
        typecount = sum(b.materialtype == type for b in duesoon)
        if typecount>0:
            returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
    totalreturnbooks = len(duesoon)
    returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"    
    returntable += tableend + "<br>"
    returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+ th + "Renewal Status" + th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
    for item in duesoon:
        returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount)  + td + str(item.renewresult)+ td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
    returntable += tableend + "<BR>"
returnlist = [d for d in allbooks if (d.renewalcount == 3)]
if len(returnlist) == 0:
    pass
else:
    returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
    for type in mediatypes:
        typecount = sum(b.materialtype == type for b in returnlist)
        if typecount>0:
            returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
    totalreturnbooks = len(returnlist)
    returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"    
    returntable += tableend + "<br>"
    returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
    for item in returnlist:
        returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
    returntable += tableend
returnlist = [d for d in allbooks if (d.renewalcount == 2)]
if len(returnlist) == 0:
    pass
else:
    returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
    for type in mediatypes:
        typecount = sum(b.materialtype == type for b in returnlist)
        if typecount>0:
            returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
    totalreturnbooks = len(returnlist)
    returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"    
    returntable += tableend + "<br>"
    returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
    for item in returnlist:
        returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
    returntable += tableend
returnlist = [d for d in allbooks if (d.renewalcount == 1)]
if len(returnlist) == 0:
    pass
else:
    returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
    for type in mediatypes:
        typecount = sum(b.materialtype == type for b in returnlist)
        if typecount>0:
            returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
    totalreturnbooks = len(returnlist)
    returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"    
    returntable += tableend + "<br>"
    returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
    for item in returnlist:
        returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
    returntable += tableend
returnlist = [d for d in allbooks if (d.renewalcount == 0)]
if len(returnlist) == 0:
    pass
else:
    returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
    for type in mediatypes:
        typecount = sum(b.materialtype == type for b in returnlist)
        if typecount>0:
            returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
    totalreturnbooks = len(returnlist)
    returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"    
    returntable += tableend + "<br>"
    returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
    for item in returnlist:
        returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
    returntable += tableend
htmltable = returntable
with open("/var/www/html/index.html","w",encoding='utf-8') as outhtml:
    outhtml.write(htmltable)
sendemail(htmltable,"Checked Out Library Books Report " + str(datetime.date.today()))
#for item in duesoon:
#    item.print()