#!/usr/bin/env python3
"""
📚 doks: Automatic READMEs from code 📚
====================================================================

Reads the comments from your file and puts them into a servicable .rst
file.

Very suitable for single-file Python libraries that want to keep the code
and documentation in sync without issues

USAGE
-------

.. code-block:: bash

    doks my_file.py [README.rst]

"""
from . import from_command
from . import from_file
from .rst import render
from pathlib import Path
import datetime
import safer
import sys

README = 'README.rst'

__all__ = ('doks',)


def doks(
    source=None,
    target=None,
    auto=False,
    command=False,
    force=False,
    window=None,
    verbose=False,
):
    """
    Write documentation for a file or module.
    Returns True if `target` was written, and False if it was unchanged.

    ARGUMENTS
      source
        path to the Python file or module.

      target
        path to the output file or `None`, in which case
        output is printed to stdout

      auto
        If true, automatically guess both source and target files

      command
        If true, use command line help from executing source file

      force
        If true, write .rst documentation even if it is malformed

      verbose
        Emit more print messages
    """
    if auto:
        source = source or _guess_source()
        target = target or README

    elif not source:
        raise ValueError('Source must be set if --auto/-a is not used')

    if window is None:
        window = render.ERROR_WINDOW

    if command:
        lines = from_command.from_command(source)
    else:
        lines = from_file.from_file(source)
    lines = list(lines)

    if lines and lines[-1]:
        lines.append('')
    lines.append(_DOKS_MSG % _timestamp())

    body = '\n'.join(lines) + '\n'
    if not (render.render(body, window) or force):
        raise ValueError(f'The .rst code in {source} is malformed')

    if not target:
        print(body)
        return True

    p = Path(target)
    written = 'rewritten' if p.exists() else 'written'
    if p.exists() and p.read_text().splitlines()[:-1] == lines[:-1]:
        print(f'{target} unchanged', file=sys.stderr)
        return False

    with safer.writer(target) as fp:
        fp.write(body)

    print(f'{target} {written}', file=sys.stderr)
    return True


def _guess_source():
    eponymous = Path(Path().absolute().stem + '.py')
    if eponymous.exists():
        return eponymous

    def accept(p):
        if p.suffix == '.py' and p.name != 'setup.py':
            return not (p.name.startswith('test') or p.name.startswith('.'))

    files = sorted(p for p in Path().iterdir() if accept(p))
    if not files:
        raise ValueError('No Python files to document')
    if len(files) > 1:
        files = ', '.join(str(f) for f in files)
        raise ValueError(f'Too many possible Python files: {files}')
    return files[0]


def _timestamp():
    return datetime.datetime.now().isoformat()


_DOKS_URL = 'https://github.com/rec/doks/'
_DOKS_MSG = f'(automatically generated by `doks <{_DOKS_URL}>`_ on %s)'
