# -*- coding: utf-8 -*-

"""Main module."""
import json
import shlex
import subprocess as sp
import typing as T
from pathlib import Path

from jinja2 import Environment

from ninjadog.constants import PUG_CLI_PATH
from ninjadog.utils import jsonify


def render(string: str = '',
           file: T.Union[Path, str] = None,
           context: T.Any = None,
           pretty: bool = False,
           pug_cli_path: str = None,
           with_jinja: bool = False) -> str:
    """
    Render a pug template through the pug cli.

    Args:
        string: a string in pug syntax to be rendered
        file: the path to a pug template
        context: the data to be passed to the template
        pretty: pretty html output
        pug_cli_path: path to the pug cli
        with_jinja: render jinja2 template syntax as well

    Returns: rendered html

    """

    if pug_cli_path is None and PUG_CLI_PATH is None:
        msg = "the pug command was not found. Did you install it?\n" \
              "brew install npm\n" \
              "npm install -g pug-cli"
        raise ValueError(msg)
    elif pug_cli_path is None:
        pug_cli_path = PUG_CLI_PATH

    # create Path object if file argument is given
    # Path() is idempotent so this shouldn't make any difference
    # if the file argument is of type Path
    filepath = Path(str(file)) if file is not None else file

    # if filepath is given instead of a string argument,
    # return render of string
    if filepath and not string:
        with filepath.open() as fp:
            return render(fp.read(),
                          filepath,
                          context=context,
                          pretty=pretty,
                          pug_cli_path=pug_cli_path,
                          with_jinja=with_jinja,
                          )

    cmd = shlex.quote(pug_cli_path)
    path = '-p {}'.format(shlex.quote(str(filepath))) if filepath else ''
    pretty_print = '-P' if pretty else ''

    if context is None:
        context_arg = ''
    elif isinstance(context, str):
        context_arg = '-O {}'.format(shlex.quote(context))
    else:
        context_arg = '-O {}'.format(shlex.quote(jsonify(context)))

    # jinja templates require pre and post-processing
    if with_jinja:
        env = Environment()
        env.globals = context
        if isinstance(context, str):
            context = json.loads(context)
        string = env.from_string(string).render()

    pug_cli = sp.Popen(shlex.split('{} {} {} {}'.format(cmd, context_arg, path, pretty_print)),
                       stdin=sp.PIPE,
                       stdout=sp.PIPE,
                       cwd=str(filepath.parent) if filepath else None,
                       universal_newlines=True,
                       )
    html, _ = pug_cli.communicate(string)

    return html if not with_jinja else env.from_string(html).render()

