import os
import re

from av1an.project import Project
from av1an.chunk import Chunk
from av1an.commandtypes import MPCommands, CommandPair, Command
from .encoder import Encoder
from av1an.utils import list_index_of_regex


class X264(Encoder):
    def __init__(self):
        super().__init__(encoder_bin='x264',
                         encoder_help='x264 --fullhelp',
                         default_args=['--preset', 'slow', '--crf', '25'],
                         default_passes=1,
                         default_q_range=(15, 35),
                         output_extension='mkv')

    def compose_1_pass(self, a: Project, c: Chunk, output: str) -> MPCommands:
        return [
            CommandPair(Encoder.compose_ffmpeg_pipe(a), [
                'x264', '--stitchable', '--log-level', 'error', '--demuxer',
                'y4m', *a.video_params, '-', '-o', output
            ])
        ]

    def compose_2_pass(self, a: Project, c: Chunk, output: str) -> MPCommands:
        return [
            CommandPair(Encoder.compose_ffmpeg_pipe(a), [
                'x264', '--stitchable', '--log-level', 'error', '--pass', '1',
                '--demuxer', 'y4m', *a.video_params, '-', '--stats',
                f'{c.fpf}.log', '-', '-o', os.devnull
            ]),
            CommandPair(Encoder.compose_ffmpeg_pipe(a), [
                'x264', '--stitchable', '--log-level', 'error', '--pass', '2',
                '--demuxer', 'y4m', *a.video_params, '-', '--stats',
                f'{c.fpf}.log', '-', '-o', output
            ])
        ]

    def man_q(self, command: Command, q: int) -> Command:
        """Return command with new cq value

        :param command: old command
        :param q: new cq value
        :return: command with new cq value"""

        adjusted_command = command.copy()

        i = list_index_of_regex(adjusted_command, r"--crf")
        adjusted_command[i + 1] = f'{q}'

        return adjusted_command

    def match_line(self, line: str):
        """Extract number of encoded frames from line.

        :param line: one line of text output from the encoder
        :return: match object from re.search matching the number of encoded frames"""

        return re.search(r"^[^\d]*(\d+)", line)
