#!/usr/bin/env python3
"""
Save all Markdown documents in your CodiMD history to a local directory.
"""

import json
from pathlib import Path
from urllib.error import HTTPError
from urllib.parse import quote
from urllib.request import Request, urlopen
import sys

from common import get_sessionid, check_accessibility, print_block_heading


def slurp(url, session_id):
    """Retrieve a (protected) CodiMD resource and return it as a bytes object."""
    request = Request(url, headers={"Cookie": f"connect.sid={session_id}"})
    with urlopen(request) as stream:
        return stream.read()


def prepare_target_dir(pathname):
    """Create the directory to dump documents to, but refuse to override an existing one."""
    target_dir = Path(pathname)
    if target_dir.exists():
        raise SystemExit(f"ERROR: the target directory {target_dir} already exists. Delete it, then re-execute this "
                         f"script")
    target_dir.mkdir()
    return target_dir


def export_from_codimd(instance_url, session_id, export_to):
    check_accessibility(instance_url, session_id, "connect.sid")
    """Retrieve CodiMD document history and try to download each document."""
    print_block_heading(f"Trying to fetch history ({instance_url})")
    try:
        data = json.loads(slurp(f"{instance_url}/history", session_id))
    except OSError as error:
        raise SystemExit(f"error: couldn't access the /history endpoint: {error}")
    except json.JSONDecodeError as error:
        raise SystemExit(f"error: received malformed JSON: {error}")
    print_block_heading(f"Preparing target directory ({export_to})")
    target_dir = prepare_target_dir(export_to)
    num_ok = num_fail = 0
    print_block_heading(f"Accessing history and trying to fetch each document")
    for row in data["history"]:
        document_id = row["id"]
        document_url = f"{instance_url}/{quote(document_id)}"
        try:
            contents = slurp(f"{document_url}/download", session_id)
            with open(Path(target_dir, f"{document_id}.md"), mode="wb") as stream:
                stream.write(contents)
            with open(Path(target_dir, f"history.json"), mode="w") as stream:
                json.dump(data, stream)
            num_ok += 1
        except HTTPError as error:
            # history might reference deleted or otherwise inaccessible notes
            error_msg = f"HTTP {error.code} {error.reason}"
            print(f"{error_msg}: {document_url}", file=sys.stderr)
            num_fail += 1
    print(f"Done: {num_ok} notes successfully downloaded, {num_fail} not accessible.")


if __name__ == "__main__":
    export_from_codimd("https://md.inf.tu-dresden.de", get_sessionid("CodiMD", "connect.sid"), "codimd-documents")