### python rewrite of auto-gen-bookmarks.jl
from os import environ
from platform import system
import argparse
from agb_funcs import *
from pathlib import Path

### setup for `makeOrgEntries()` and `makeMarkdownEntries()`
org_string_to_write = f"""# -*- mode: org -*-
# vim: set filetype=org :
#+TITLE: Browser Bookmarks
#+DATE: {datetime.date.today().strftime("%Y-%m-%d")}
#+STARTUP: fold

* NOTE
This file was auto generated by the script [[./auto-gen-bookmarks.py][auto-gen-bookmarks.py]].
Editing by hand is not recommended.
"""

markdown_string_to_write = f"""---
title: Browser Bookmarks
date: {datetime.date.today().strftime("%Y-%m-%d")}
---

# NOTE
This file was auto generated by the script [auto-gen-bookmarks.py](auto-gen-bookmarks.py).
Editing by hand is not recommended.
"""


def makeOrgEntries(data_dict: dict, headline_level: int = 1):
    """
        makeOrgEntries(data_dict: dict, headline_level: int = 1)

    Function that will iterate over the JSON object to create string using Emacs
    Org Mode syntax that can be written to a file. It uses global scope for its
    "org_string_to_write" variable, and utilizes a keyword argument
    "headline_level" to achieve this.

    Within the for loop, this function implements a conditional to check if the
    value it is on is a *folder* or a *url*. If the value is a folder, it will
    create a headline of the appropriate level based on the "headline_level"
    variable and the name of the folder. It will then recursively call itself on
    the folder's children, with the "headline_level" keyword argument
    incremented by one, to iterate through the whole of the JSON string. If the
    conditional finds the item is not a folder, it will create Org Mode
    bullet-point entries with appropriate Org Mode links based on the item's
    name and url."""
    if type(data_dict) == list:
        ## it could be a list of dicts
        for value in data_dict:
            if value["type"] == "folder":
                txt_to_cat_fldr: str = (
                    "\n" + ("*" * headline_level) + " " + value["name"]
                )
                global org_string_to_write
                org_string_to_write = org_string_to_write + txt_to_cat_fldr
                makeOrgEntries(value["children"], headline_level=headline_level + 1)
            else:
                txt_to_cat: str = (
                    "\n" + f"""- [[{value.get("url")}][{value.get("name")}]]"""
                )
                org_string_to_write = org_string_to_write + txt_to_cat
    else:
        ## for loop to iterate over all dict contents
        for value in data_dict.values():
            ## check if we're on a folder
            if value["type"] == "folder":
                ## if we're on a folder, add a headline to the string matching the
                ## folder name, and recursively call this function on the folder
                ## value itself to continue
                txt_to_cat_fldr: str = (
                    "\n" + ("*" * headline_level) + " " + value["name"]
                )
                org_string_to_write = org_string_to_write + txt_to_cat_fldr
                makeOrgEntries(value["children"], headline_level=headline_level + 1)
            else:
                ## append the link in proper org format, and add a newline to the end
                txt_to_cat: str = (
                    "\n" + f"""- [[{value.get("url")}][{value.get("name")}]]"""
                )
                org_string_to_write = org_string_to_write + txt_to_cat


def makeMarkdownEntries(data_dict: dict, headline_level: int = 1):
    """
        makeMarkdownEntries(data_dict: dict, headline_level: int = 1)

    Function that will iterate over the JSON object to create string using markdown
    syntax that can be written to a file. It uses global scope for its
    "markdown_string_to_write" variable, and utilizes a keyword argument
    "headline_level" to achieve this.

    Within the for loop, this function implements a conditional to check if the
    value it is on is a folder or a url. If the value is a folder, it will
    create a headline of the appropriate level based on the "headline_level"
    variable and the name of the folder. It will then recursively call itself on the
    folder's children, with the "headline_level" keyword argument incremented by
    one, to iterate through the whole of the JSON string. If the conditional finds
    the item is not a folder, it will create markdown bullet-point entries with
    appropriate markdown links based on the item's name and url.
    """
    if type(data_dict) == list:
        ## it could be a list of dicts
        for value in data_dict:
            if value["type"] == "folder":
                txt_to_cat_fldr: str = (
                    "\n\n" + ("#" * headline_level) + " " + value["name"]
                )
                global markdown_string_to_write
                markdown_string_to_write = markdown_string_to_write + txt_to_cat_fldr
                makeMarkdownEntries(
                    value["children"], headline_level=headline_level + 1
                )
            else:
                txt_to_cat: str = (
                    "\n" + f"""- [{value.get("name")}]({value.get("url")})"""
                )
                markdown_string_to_write = markdown_string_to_write + txt_to_cat
    else:
        ## for loop to iterate over all dict contents
        for value in data_dict.values():
            ## check if we're on a folder
            if value["type"] == "folder":
                ## if we're on a folder, add a headline to the string matching the
                ## folder name, and recursively call this function on the folder
                ## value itself to continue
                txt_to_cat_fldr: str = (
                    "\n" + ("*" * headline_level) + " " + value["name"]
                )
                markdown_string_to_write = markdown_string_to_write + txt_to_cat_fldr
                makeMarkdownEntries(
                    value["children"], headline_level=headline_level + 1
                )
            else:
                ## append the link in proper markdown format, and add a newline to the end
                txt_to_cat: str = (
                    "\n" + f"""- [{value.get("name")}]({value.get("url")})"""
                )
                markdown_string_to_write = markdown_string_to_write + txt_to_cat


### parse args given from the commandline
def parseCommandline():
    prog_desc: str = "Program to read the JSON that the Brave browser stores its bookmarks info in and create an org mode (or markdown) file containing said bookmarks from it."
    parser = argparse.ArgumentParser(description=prog_desc)
    parser.add_argument(
        "-p",
        "--profile_num",
        help="The profile to take the bookmarks from. If zero is entered, the program reads from the profile named 'Default'. This argument defaults to 0",
        type=int,
        default=0,
    )
    parser.add_argument(
        "-o",
        "--outfile_name",
        help="The name of the file produced by the script and written to the disk.",
        type=str,
    )
    parser.add_argument(
        "-m",
        "--as_markdown",
        help="Make the file produced be in markdown format instead of the default org-mode.",
        action="store_true",
    )
    parser.add_argument(
        "-P",
        "--post_process",
        help="Convert the file to some format after the markdown or org mode \
        document is produced. This uses the program pandoc, and this \
        functionality requires it as a dependency.",
        action="store_true",
    )
    parser.add_argument(
        "-t",
        "--pandoc_out_format",
        help="Format to pass to pandoc as the type of the output format. \
        Suggestions are pdf, docx, html, and others that play nicely with \
        naming. Use in conjunction with -P. This argument will default to \
        html.",
        type=str,
        default="html",
    )
    parser.add_argument(
        "-k",
        "--keep_pp_file",
        help="This flag will cause the intermediate markdown or org mode file \
        produced to be kept. Use in conjunction with -P.",
        action="store_true",
    )
    return parser.parse_args()


def main():
    ## parse the arguments
    parsed_args = parseCommandline()

    ## parse the bookmarks
    prof_num: int = parsed_args.profile_num
    if system() == "Windows":
        if prof_num == 0:
            bkmks_file = f"{environ['HOME']}\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Bookmarks"
        else:
            bkmks_file = f"{environ['HOME']}\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Profile {prof_num}\\Bookmarks"
    else:
        if prof_num == 0:
            bkmks_file = (
                "~/.config/BraveSoftware/Brave-Browser/User Data/Default/Bookmarks"
            )
        else:
            bkmks_file = f"~/.config/BraveSoftware/Brave-Browser/User Data/Profile {prof_num}/Bookmarks"
    data = parseJSON(loadFile(bkmks_file))

    ## setup for `makeOrgEntries()` and `makeMarkdownEntries()`
    # done at the beginning because global vars have to be defined before they are used

    ## make the string for the output file
    makeMarkdownEntries(data) if parsed_args.as_markdown else makeOrgEntries(data)

    ## write the string to a file
    md_output_file_default: str = (
        f"bookmarks.profile-{prof_num}.md"  # set some defaults
    )
    org_output_file_default: str = (
        f"bookmarks.profile-{prof_num}.org"  # set some defaults
    )

    ## save the file in a platform agnostic way
    bookmark_dir = Path(environ["BOOKMARK_FILE_DIR"])
    if parsed_args.outfile_name != None:
        output_file = parsed_args.outfile_name
    elif parsed_args.as_markdown:
        output_file = Path(bookmark_dir, md_output_file_default)
    else:
        output_file = Path(bookmark_dir, org_output_file_default)

    if parsed_args.as_markdown:
        writeFile(markdown_string_to_write, output_file)
    else:
        writeFile(org_string_to_write, output_file)
    print(f"Saved to:\n\t{output_file}")  # let user know where the output was saved

    ## post process, if the user asked for it
    if parsed_args.post_process:
        final_file: str = Path(output_file).stem + "." + parsed_args.pandoc_out_format
        if parsed_args.as_markdown:
            post_process(
                output_file,
                "markdown",
                parsed_args.pandoc_out_format,
                final_file,
                parsed_args.keep_pp_file,
            )
        else:
            post_process(
                output_file,
                "org",
                parsed_args.pandoc_out_format,
                final_file,
                parsed_args.keep_pp_file,
            )


if __name__ == "__main__":
    main()
