# ffmpeg only backend

import locale
import logging
import re
from subprocess import PIPE, Popen

logger = logging.getLogger(__name__)


class VideoEncodingError(Exception):
    def __init__(self, *args, **kwargs):
        self.message = args[0]
        super(VideoEncodingError, self).__init__(*args, **kwargs)


RE_TIMECODE = re.compile(r"time=(\d+:\d+:\d+.\d+)")
console_encoding = locale.getdefaultlocale()[1] or "UTF-8"


class FFmpegBackend(object):
    name = "FFmpeg"

    def __init__(self):
        pass

    def _spawn(self, cmd):
        try:
            return Popen(
                cmd,
                shell=False,
                stdin=PIPE,
                stdout=PIPE,
                stderr=PIPE,
                close_fds=True,
            )
        except OSError as e:
            raise VideoEncodingError("Error while running ffmpeg", e)

    def _check_returncode(self, process):
        ret = {}
        stdout, stderr = process.communicate()
        ret["code"] = process.returncode
        return ret

    def encode(self, cmd):
        process = self._spawn(cmd)
        buf = output = ""
        while True:
            out = process.stderr.read(10)

            if not out:
                break
            try:
                out = out.decode(console_encoding)
            except UnicodeDecodeError:
                out = ""
            output = output[-500:] + out
            buf = buf[-500:] + out
            try:
                line, buf = buf.split("\r", 1)
            except BaseException:
                continue

            progress = RE_TIMECODE.findall(line)
            if progress:
                progress = progress[0]
            yield progress

        process_check = self._check_returncode(process)
        if process_check["code"] != 0:
            raise VideoEncodingError(output[-1000:])  # output could be huge

        if not output:
            raise VideoEncodingError("No output from FFmpeg.")

        yield output[-1000:]  # output could be huge
