import os

import aiojobs.aiohttp

import virtool.db.hmm
import virtool.db.processes
import virtool.db.status
import virtool.db.utils
import virtool.hmm
import virtool.http.routes
import virtool.utils
from virtool.api.utils import compose_regex_query, json_response, no_content, not_found, paginate

routes = virtool.http.routes.Routes()


@routes.get("/api/hmms")
async def find(req):
    """
    Find HMM annotation documents.

    """

    db = req.app["db"]

    term = req.query.get("find", None)

    db_query = dict()

    if term:
        db_query.update(compose_regex_query(term, ["names"]))

    data = await paginate(
        db.hmm,
        db_query,
        req.query,
        sort="cluster",
        projection=virtool.db.hmm.PROJECTION,
        base_query={"hidden": False}
    )

    data["status"] = await virtool.db.status.get_hmm_status(db)

    return json_response(data)


@routes.get("/api/hmms/status")
async def get_status(req):
    db = req.app["db"]
    status = await virtool.db.status.get_hmm_status(db)

    return json_response(status)


@routes.get("/api/hmms/release")
async def get_release(req):
    release = await virtool.db.status.fetch_and_update_hmm_release(req.app)
    return json_response(release)


@routes.get("/api/hmms/updates")
async def list_updates(req):
    """
    List all updates applied to the HMM collection.

    """
    db = req.app["db"]

    updates = await virtool.db.utils.get_one_field(db.status, "updates", "hmm")

    if updates:
        updates.reverse()

    return json_response(updates or list())


@routes.post("/api/hmms/updates", schema={
    "release_id": {
        "type": "string",
        "default": "latest"
    }
})
async def install(req):
    """
    Install the latest official HMM database from GitHub.

    """
    release_id = req["data"]["release_id"]

    print(release_id)

    db = req.app["db"]

    process = await virtool.db.processes.register(
        db,
        "install_hmms"
    )

    document = await db.status.find_one_and_update({"_id": "hmm"}, {
        "$set": {
            "process": {
                "id": process["id"]
            }
        }
    })

    await aiojobs.aiohttp.spawn(req, virtool.db.hmm.install(
        req.app,
        process["id"],
        release_id,
        req["client"].user_id
    ))

    return json_response(virtool.utils.base_processor(document))


@routes.get("/api/hmms/{hmm_id}")
async def get(req):
    """
    Get a complete individual HMM annotation document.

    """
    document = await req.app["db"].hmm.find_one({"_id": req.match_info["hmm_id"]})

    if document is None:
        return not_found()

    return json_response(virtool.utils.base_processor(document))


@routes.delete("/api/hmms")
async def purge(req):
    """
    Delete all unreferenced HMMs and hide the rest.

    """
    db = req.app["db"]

    await virtool.db.hmm.purge(db)

    hmm_path = os.path.join(req.app["settings"]["data_path"], "hmm/profiles.hmm")

    try:
        await req.app["run_in_thread"](virtool.utils.rm, hmm_path)
    except FileNotFoundError:
        pass

    await db.status.find_one_and_update({"_id": "hmm"}, {
        "$set": {
            "process": None,
            "ready": False,
            "updates": list()
        }
    })

    await virtool.db.status.fetch_and_update_hmm_release(req.app)

    return no_content()

@@ -127,16 +127,38 @@
 b.utils%0A
+import virtool.github%0A
 import v
@@ -164,24 +164,24 @@
 virtool.hmm%0A
-
 import virto
@@ -266,16 +266,26 @@
 x_query,
+ conflict,
  json_re
@@ -463,17 +463,16 @@
     %22%22%22%0A
-%0A
     db =
@@ -1115,16 +1115,23 @@
 pi/hmms/
+status/
 release%22
@@ -1287,32 +1287,39 @@
 .get(%22/api/hmms/
+status/
 updates%22)%0Aasync 
@@ -1600,24 +1600,24 @@
 r list())%0A%0A%0A
-
 @routes.post
@@ -1628,16 +1628,23 @@
 pi/hmms/
+status/
 updates%22

Update HMM API URLs