#!/usr/bin/env python
# encoding: utf-8

"""Implements `echo hi` shell code interpolation."""

import os
import platform
from subprocess import Popen, PIPE
import stat
import tempfile

from UltiSnips.compatibility import as_unicode
from UltiSnips.text_objects._base import NoneditableTextObject


def _chomp(string):
    """Rather than rstrip(), remove only the last newline and preserve
    purposeful whitespace."""
    if len(string) and string[-1] == '\n':
        string = string[:-1]
    if len(string) and string[-1] == '\r':
        string = string[:-1]
    return string


def _run_shell_command(cmd, tmpdir):
    """Write the code to a temporary file."""
    cmdsuf = ''
    if platform.system() == 'Windows':
        # suffix required to run command on windows
        cmdsuf = '.bat'
        # turn echo off
        cmd = '@echo off\r\n' + cmd
    handle, path = tempfile.mkstemp(text=True, dir=tmpdir, suffix=cmdsuf)
    os.write(handle, cmd.encode('utf-8'))
    os.close(handle)
    os.chmod(path, stat.S_IRWXU)

    # Execute the file and read stdout
    proc = Popen(path, shell=True, stdout=PIPE, stderr=PIPE)
    proc.wait()
    stdout, _ = proc.communicate()
    os.unlink(path)
    return _chomp(as_unicode(stdout))


def _get_tmp():
    """Find an executable tmp directory."""
    userdir = os.path.expanduser('~')
    for testdir in [tempfile.gettempdir(), os.path.join(userdir, '.cache'),
                    os.path.join(userdir, '.tmp'), userdir]:
        if (not os.path.exists(testdir) or
                not _run_shell_command('echo success', testdir) == 'success'):
            continue
        return testdir
    return ''


class ShellCode(NoneditableTextObject):

    """See module docstring."""

    def __init__(self, parent, token):
        NoneditableTextObject.__init__(self, parent, token)
        self._code = token.code.replace('\\`', '`')
        self._tmpdir = _get_tmp()

    def _update(self, done):
        if not self._tmpdir:
            output = \
                'Unable to find executable tmp directory, check noexec on /tmp'
        else:
            output = _run_shell_command(self._code, self._tmpdir)
        self.overwrite(output)
        self._parent._del_child(self)  # pylint:disable=protected-access
        return True
