import hashlib
import urllib
import falcon
import sqlite3
import platform
import base64
import requests
import dateutil.parser
from datetime import datetime
from waitress import serve


class GravatarCachedResource:
    def __init__(self):
        self.isCached = False
        self.connection = sqlite3.connect('database.db')
        self.cursor = self.connection.cursor()
        self.cursor.execute('''
        CREATE TABLE IF NOT EXISTS "cache" (
            "id"	TEXT NOT NULL,
            "created_at"	TEXT NOT NULL,
            "data"	BLOB,
            PRIMARY KEY("id")
        );
        ''')

        self.cursor.execute('''
        CREATE TABLE IF NOT EXISTS "history" (
            "id"	INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            "date"	TEXT NOT NULL,
            "url"	TEXT NOT NULL
        );
        ''')

    def get_username_hash(self, username):
        return hashlib.md5(username.encode('utf-8')).hexdigest()

    def get_gravatar_url(self, username):
        gravatar_url = 'https://r...content-available-to-author-only...r.com/avatar/' + self.get_username_hash(username) + '?'
        gravatar_url += urllib.parse.urlencode({'s':  str(300)})
        return gravatar_url

    def get_gravatar_image(self, username):
        url = self.get_gravatar_url(username)
        return requests.get(url).content

    def get_current_datetime(self):
        return datetime.now().isoformat()

    def parse_datetime(self, date):
        return dateutil.parser.parse(date)

    def save_image_to_database(self, username):
        username_hash = self.get_username_hash(username)
        image = self.get_gravatar_image(username)
        current_datetime = self.get_current_datetime()

        if self.get_image_from_database(username) is None:
            self.cursor.execute("INSERT INTO `cache` VALUES (?, ?, ?);", (username_hash, current_datetime, image))
        else:
            self.cursor.execute("UPDATE `cache` SET `created_at` = ?, `data` = ? WHERE `id` = ?;", (current_datetime, image, username_hash))

        self.connection.commit()

    def get_image_from_database(self, username):
        username_hash = self.get_username_hash(username)
        self.cursor.execute("SELECT * FROM `cache` WHERE `cache`.`id` = '{}'".format(username_hash))
        return self.cursor.fetchone()

    def get_image_from_cache_of_download(self, username):
        data = self.get_image_from_database(username)

        if (data):
            now = datetime.now()
            created_at = self.parse_datetime(data[1])
            delta_in_seconds = (now - created_at).total_seconds()

            if delta_in_seconds < 15:
                self.isCached = True
                return data[2]

        self.isCached = False
        self.save_image_to_database(username)
        return self.get_gravatar_image(username)

    def save_action_to_history(self, req, ):
        current_datetime = self.get_current_datetime()

        self.cursor.execute("INSERT INTO `history` (date, url) VALUES (?, ?);", (current_datetime, req.url))

    def on_get(self, req, resp, username):
        self.connection = sqlite3.connect('database.db')
        self.cursor = self.connection.cursor()

        self.save_action_to_history(req)

        image = self.get_image_from_cache_of_download(username)
        encoded = base64.b64encode(image).decode('utf-8')

        resp.content_type = 'text/html'
        resp.body = '<h3>From {0}</h3><img src="data:image/png;base64, {1}">'.format('cache' if self.isCached else 'site' , encoded)
        resp.status = falcon.HTTP_200

class Info:
    def on_get(self, req, resp):
        self.connection = sqlite3.connect('database.db')

        self.save_action_to_history(req)
        resp.content_type = 'text/html'
        resp.body = f'''
        <h3>System information</h3>
        <ul style="border: 2px solid black">
            <li>Architecture: {platform.architecture()[0]}</li>
            <li>CP: {platform.machine()}</li>
            <li>Name: {platform.node()}</li>
            <li>OS: {platform.system()}</li>
        </ul>
        '''

        resp.status = falcon.HTTP_200

class History:
    def on_get(self, req, resp):
        self.connection = sqlite3.connect('database.db')
        self.cursor = self.connection.cursor()
        self.cursor.execute("SELECT * FROM `history`")

        data = self.cursor.fetchall()
        table_data = ''

        for row in data:
            table_data += f'<tr><td>{row[1]}</td><td>{row[2]}</td></tr>'

        resp.content_type = 'text/html'
        resp.body = '<h3>History</h3><table><tr><td>date</td><td>url</td></tr>{}</table>'.format(table_data)
        resp.status = falcon.HTTP_200


api = falcon.API()

api.add_route('/api/info', Info())
api.add_route('/api/history', History())
api.add_route('/api/avatar/{username}', GravatarCachedResource())

serve(api, host = '127.0.0.1', port = 8000)