from sqlalchemy import Table, Column, Integer, String, MetaData
from sqlalchemy.sql import select, text
from sqlalchemy import func

import ckan.model as model

cached_tables = {}


def init_tables():
    metadata = MetaData()
    Table(
        "package_stats",
        metadata,
        Column("package_id", String(60), primary_key=True),
        Column("visits_recently", Integer),
        Column("visits_ever", Integer),
    )
    Table(
        "resource_stats",
        metadata,
        Column("resource_id", String(60), primary_key=True),
        Column("visits_recently", Integer),
        Column("visits_ever", Integer),
    )
    metadata.create_all(model.meta.engine)


def get_table(name):
    if name not in cached_tables:
        meta = MetaData()
        meta.reflect(bind=model.meta.engine)
        table = meta.tables[name]
        cached_tables[name] = table
    return cached_tables[name]


def _update_visits(table_name, item_id, recently, ever):
    stats = get_table(table_name)
    id_col_name = "%s_id" % table_name[: -len("_stats")]
    id_col = getattr(stats.c, id_col_name)
    s = select([func.count(id_col)], id_col == item_id)
    connection = model.Session.connection()
    count = connection.execute(s).fetchone()
    if count and count[0]:
        connection.execute(
            stats.update()
            .where(id_col == item_id)
            .values(visits_recently=recently, visits_ever=ever)
        )
    else:
        values = {
            id_col_name: item_id,
            "visits_recently": recently,
            "visits_ever": ever,
        }
        connection.execute(stats.insert().values(**values))


def update_resource_visits(resource_id, recently, ever):
    return _update_visits("resource_stats", resource_id, recently, ever)


def update_package_visits(package_id, recently, ever):
    return _update_visits("package_stats", package_id, recently, ever)


def get_resource_visits_for_url(url):
    connection = model.Session.connection()
    count = connection.execute(
        text(
            """SELECT visits_ever FROM resource_stats, resource
        WHERE resource_id = resource.id
        AND resource.url = :url"""
        ),
        url=url,
    ).fetchone()
    return count and count[0] or ""


""" get_top_packages is broken, and needs to be rewritten to work with
CKAN 2.*. This is because ckan.authz has been removed in CKAN 2.*

See commit ffa86c010d5d25fa1881c6b915e48f3b44657612
"""


def get_top_packages(limit=20):
    items = []
    # caveat emptor: the query below will not filter out private
    # or deleted datasets (TODO)
    q = model.Session.query(model.Package)
    connection = model.Session.connection()
    package_stats = get_table("package_stats")
    s = select(
        [
            package_stats.c.package_id,
            package_stats.c.visits_recently,
            package_stats.c.visits_ever,
        ]
    ).order_by(package_stats.c.visits_recently.desc())
    res = connection.execute(s).fetchmany(limit)
    for package_id, recent, ever in res:
        item = q.filter(text("package.id = '%s'" % package_id))
        if not item.count():
            continue
        items.append((item.first(), recent, ever))
    return items


def get_top_resources(limit=20):
    items = []
    connection = model.Session.connection()
    resource_stats = get_table("resource_stats")
    s = select(
        [
            resource_stats.c.resource_id,
            resource_stats.c.visits_recently,
            resource_stats.c.visits_ever,
        ]
    ).order_by(resource_stats.c.visits_recently.desc())
    res = connection.execute(s).fetchmany(limit)
    for resource_id, recent, ever in res:
        item = model.Session.query(model.Resource).filter(
            "resource.id = '%s'" % resource_id
        )
        if not item.count():
            continue
        items.append((item.first(), recent, ever))
    return items

@@ -2257,974 +2257,8 @@
 %22%0A%0A%0A
-%22%22%22 get_top_packages is broken, and needs to be rewritten to work with%0ACKAN 2.*. This is because ckan.authz has been removed in CKAN 2.*%0A%0ASee commit ffa86c010d5d25fa1881c6b915e48f3b44657612%0A%22%22%22%0A%0A%0Adef get_top_packages(limit=20):%0A    items = %5B%5D%0A    # caveat emptor: the query below will not filter out private%0A    # or deleted datasets (TODO)%0A    q = model.Session.query(model.Package)%0A    connection = model.Session.connection()%0A    package_stats = get_table(%22package_stats%22)%0A    s = select(%0A        %5B%0A            package_stats.c.package_id,%0A            package_stats.c.visits_recently,%0A            package_stats.c.visits_ever,%0A        %5D%0A    ).order_by(package_stats.c.visits_recently.desc())%0A    res = connection.execute(s).fetchmany(limit)%0A    for package_id, recent, ever in res:%0A        item = q.filter(text(%22package.id = '%25s'%22 %25 package_id))%0A        if not item.count():%0A            continue%0A        items.append((item.first(), recent, ever))%0A    return items%0A%0A%0A
 def 

Remove broken method