""" Tools for Sphinx to build docs and/or websites.
"""

import os
import os.path as op
import sys
import shutil


if sys.version_info[0] < 3:
    input = raw_input  # noqa


def sh(cmd):
    """Execute command in a subshell, return status code."""
    return subprocess.check_call(cmd, shell=True)


def sh2(cmd):
    """Execute command in a subshell, return stdout.
    Stderr is unbuffered from the subshell."""
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
    out = p.communicate()[0]
    retcode = p.returncode
    if retcode:
        raise subprocess.CalledProcessError(retcode, cmd)
    else:
        return out.rstrip().decode('utf-8', 'ignore')


def sphinx_clean(build_dir):
    if op.isdir(build_dir):
        shutil.rmtree(build_dir)
    os.mkdir(build_dir)
    print('Cleared build directory.')


def sphinx_build(src_dir, build_dir):
    import sphinx
    
    try:
        ret = 0
        ret = sphinx.main(['sphinx-build',  # Dummy
                          '-b', 'html',
                          '-d', op.join(build_dir, 'doctrees'),
                          src_dir,  # Source
                          op.join(build_dir, 'html'),  # Dest
                          ])
    except SystemExit:
        pass
    if ret != 0:
        raise RuntimeError('Sphinx error: %s' % ret)
    print("Build finished. The HTML pages are in %s/html." % build_dir)


def sphinx_show(html_dir):
    index_html = op.join(html_dir, 'index.html')
    if not op.isfile(index_html):
        sys.exit('Cannot show pages, build the html first.')
    import webbrowser
    webbrowser.open_new_tab(index_html)


def sphinx_copy_pages(html_dir, pages_dir, pages_repo):
    print('COPYING PAGES')
    # Create the pages repo if needed
    if not op.isdir(pages_dir):
        os.chdir(ROOT_DIR)
        sh("git clone %s %s" % (pages_repo, pages_dir))
    # Ensure that its up to date
    os.chdir(pages_dir)
    sh('git checkout master -q')
    sh('git pull -q')
    os.chdir('..')
    # This is pretty unforgiving: we unconditionally nuke the destination
    # directory, and then copy the html tree in there
    tmp_git_dir = op.join(ROOT_DIR, pages_dir + '_git')
    shutil.move(op.join(pages_dir, '.git'), tmp_git_dir)
    try:
        shutil.rmtree(pages_dir)
        shutil.copytree(html_dir, pages_dir)
        shutil.move(tmp_git_dir, op.join(pages_dir, '.git'))
    finally:
        if op.isdir(tmp_git_dir):
            shutil.rmtree(tmp_git_dir)
    # Copy individual files
    open(op.join(pages_dir, 'README.md'), 'wb').write(
        'Autogenerated website - do not edit\n'.encode('utf-8'))
    for fname in ['CNAME', '.nojekyll']:  # nojekyll or website wont work
        if op.isfile(op.join(WEBSITE_DIR, fname)):
            shutil.copyfile(op.join(WEBSITE_DIR, fname),
                            op.join(pages_dir, fname))
    # Messages
    os.chdir(pages_dir)
    sh('git status')
    print()
    print("Website copied to _gh-pages. Above you can see its status:")
    print("  Run 'make website show' to view.")
    print("  Run 'make website upload' to commit and push.")


def sphinx_upload(repo_dir):
    # Check head
    os.chdir(repo_dir)
    status = sh2('git status | head -1')
    branch = re.match('On branch (.*)$', status).group(1)
    if branch != 'master':
        e = 'On %r, git branch is %r, MUST be "master"' % (repo_dir,
                                                           branch)
        raise RuntimeError(e)
    # Show repo and ask confirmation
    print()
    print('You are about to commit to:')
    sh('git config --get remote.origin.url')
    print()
    print('Most recent 3 commits:')
    sys.stdout.flush()
    sh('git --no-pager log --oneline -n 3')
    ok = input('Are you sure you want to commit and push? (y/[n]): ')
    ok = ok or 'n'
    # If ok, add, commit, push
    if ok.lower() == 'y':
        sh('git add .')
        sh('git commit -am"Update (automated commit)"')
        print()
        sh('git push')
