# Path: gogdb/views/pagination.py
# def calc_pageinfo(page, num_products, items_per_page):
#     num_pages = int(math.ceil(num_products / items_per_page))
#     page = min(max(page, 1), num_pages)
#     offset = (page - 1) * items_per_page
#     page_info = {
#         "is_first": page == 1,
#         "is_last": page == num_pages,
#         "page": page,
#         "num_pages": num_pages,
#         "from": offset,
#         "to": offset + items_per_page,
#         "prev_link": "", # Filled in later
#         "next_link": ""
#     }
#     return page_info
# 
# Path: gogdb/application/datasources.py
# def get_indexdb():
#     if "indexdb" not in flask.g:
#         storagedb = get_storagedb()
#         index_path = storagedb.path_indexdb()
#         flask.g.indexdb = sqlite3.connect(index_path)
#         flask.g.indexdb.row_factory = sqlite3.Row
# 
#     return flask.g.indexdb
# 
# Path: gogdb/core/dataclsloader.py
# def class_from_json(cls, data):
#     if data is None:
#         return None
#     if dataclasses.is_dataclass(cls):
#         if cls in annotations_cache:
#             annotations = annotations_cache.get(cls)
#         else:
#             annotations = typing.get_type_hints(cls)
#             annotations_cache[cls] = annotations
#         inst = cls()
#         for field_name, field_value in data.items():
#             try:
#                 field_type = annotations[field_name]
#             except KeyError:
#                 raise KeyError("Invalid field {!r} in json. Valid fields for type {}: {!r}".format(
#                     field_name, cls, list(annotations.keys())))
#             try:
#                 field_inst = class_from_json(field_type, field_value)
#             except TypeError:
#                 raise TypeError(f"Failed to parse field {field_name}")
#             setattr(inst, field_name, field_inst)
#         return inst
#     elif get_origin(cls) is list:
#         list_element_type = get_args(cls)[0]
#         return [
#             class_from_json(list_element_type, list_element) for
#             list_element in data]
#     elif cls is datetime.datetime:
#         return datetime.datetime.fromisoformat(data)
#     else:
#         if cls is not typing.Any:
#             if not (type(data) is cls or data is None):
#                 raise TypeError(f"{repr(data)} is of type {type(data)}, {cls} required")
#         return data


import itertools
import datetime
import json
import flask
import gogdb.core.model as model
from gogdb.views.pagination import calc_pageinfo
from gogdb.application.datasources import get_indexdb
from gogdb.core.dataclsloader import class_from_json
ITEMS_PER_PAGE = 100


def changelog_ext_page(view):
    page = int(flask.request.args.get("page", "1"))

    cur = get_indexdb().cursor()
    # Get total number of entries
    cur.execute("SELECT COUNT(*) FROM changelog;")
    total_entries = cur.fetchone()[0]

    page_info = calc_pageinfo(page, total_entries, ITEMS_PER_PAGE)

    cur.execute(
        "SELECT * FROM changelog ORDER BY timestamp DESC LIMIT ? OFFSET ?;",
        (ITEMS_PER_PAGE, page_info["from"])
    )

    changes = []
    for change_res in cur:
        record_dict = json.loads(change_res["serialized_record"])
        change = model.IndexChange(
            id = change_res["product_id"],
            title = change_res["product_title"],
            timestamp = datetime.datetime.fromtimestamp(change_res["timestamp"], datetime.timezone.utc),
            action = change_res["action"],
            category = change_res["category"],
            dl_type = change_res["dl_type"],
            bonus_type = change_res["bonus_type"],
            property_name = change_res["property_name"],

# Path: gogdb/views/pagination.py
# def calc_pageinfo(page, num_products, items_per_page):
#     num_pages = int(math.ceil(num_products / items_per_page))
#     page = min(max(page, 1), num_pages)
#     offset = (page - 1) * items_per_page
#     page_info = {
#         "is_first": page == 1,
#         "is_last": page == num_pages,
#         "page": page,
#         "num_pages": num_pages,
#         "from": offset,
#         "to": offset + items_per_page,
#         "prev_link": "", # Filled in later
#         "next_link": ""
#     }
#     return page_info
# 
# Path: gogdb/application/datasources.py
# def get_indexdb():
#     if "indexdb" not in flask.g:
#         storagedb = get_storagedb()
#         index_path = storagedb.path_indexdb()
#         flask.g.indexdb = sqlite3.connect(index_path)
#         flask.g.indexdb.row_factory = sqlite3.Row
# 
#     return flask.g.indexdb
# 
# Path: gogdb/core/dataclsloader.py
# def class_from_json(cls, data):
#     if data is None:
#         return None
#     if dataclasses.is_dataclass(cls):
#         if cls in annotations_cache:
#             annotations = annotations_cache.get(cls)
#         else:
#             annotations = typing.get_type_hints(cls)
#             annotations_cache[cls] = annotations
#         inst = cls()
#         for field_name, field_value in data.items():
#             try:
#                 field_type = annotations[field_name]
#             except KeyError:
#                 raise KeyError("Invalid field {!r} in json. Valid fields for type {}: {!r}".format(
#                     field_name, cls, list(annotations.keys())))
#             try:
#                 field_inst = class_from_json(field_type, field_value)
#             except TypeError:
#                 raise TypeError(f"Failed to parse field {field_name}")
#             setattr(inst, field_name, field_inst)
#         return inst
#     elif get_origin(cls) is list:
#         list_element_type = get_args(cls)[0]
#         return [
#             class_from_json(list_element_type, list_element) for
#             list_element in data]
#     elif cls is datetime.datetime:
#         return datetime.datetime.fromisoformat(data)
#     else:
#         if cls is not typing.Any:
#             if not (type(data) is cls or data is None):
#                 raise TypeError(f"{repr(data)} is of type {type(data)}, {cls} required")
#         return data


# Path: gogdb/views/changelog_ext.py
import itertools
import datetime
import json
import flask
import gogdb.core.model as model
from gogdb.views.pagination import calc_pageinfo
from gogdb.application.datasources import get_indexdb
from gogdb.core.dataclsloader import class_from_json

ITEMS_PER_PAGE = 100


def changelog_ext_page(view):
    page = int(flask.request.args.get("page", "1"))

    cur = get_indexdb().cursor()
    # Get total number of entries
    cur.execute("SELECT COUNT(*) FROM changelog;")
    total_entries = cur.fetchone()[0]

    page_info = calc_pageinfo(page, total_entries, ITEMS_PER_PAGE)

    cur.execute(
        "SELECT * FROM changelog ORDER BY timestamp DESC LIMIT ? OFFSET ?;",
        (ITEMS_PER_PAGE, page_info["from"])
    )

    changes = []
    for change_res in cur:
        record_dict = json.loads(change_res["serialized_record"])
        change = model.IndexChange(
            id = change_res["product_id"],
            title = change_res["product_title"],
            timestamp = datetime.datetime.fromtimestamp(change_res["timestamp"], datetime.timezone.utc),
            action = change_res["action"],
            category = change_res["category"],
            dl_type = change_res["dl_type"],
            bonus_type = change_res["bonus_type"],
            property_name = change_res["property_name"],

            record = class_from_json(model.ChangeRecord, record_dict)