#!/usr/bin/env python3
import glob
import json
import logging
import os
import re
import time

from src.engines.core.base_worker import BaseRenderWorker, timecode_to_frames
from src.engines.aerender.aerender_engine import AERender


def aerender_path():
    paths = glob.glob('/Applications/*After Effects*/aerender')
    if len(paths) > 1:
        logging.warning('Multiple After Effects installations detected')
    elif not paths:
        logging.error('After Effects installation not found')
    else:
        return paths[0]


class AERenderWorker(BaseRenderWorker):

    supported_extensions = ['.aep']
    engine = AERender

    def __init__(self, input_path, output_path, args=None, parent=None, name=None):
        super(AERenderWorker, self).__init__(input_path=input_path, output_path=output_path, args=args,
                                             parent=parent, name=name)

        self.comp = args.get('comp', None)
        self.render_settings = args.get('render_settings', None)
        self.omsettings = args.get('omsettings', None)

        self.progress = 0
        self.progress_history = []
        self.attributes = {}

    def generate_worker_subprocess(self):

        if os.path.exists('nexrender-cli-macos'):
            logging.info('nexrender found')
            # {
            #     "template": {
            #         "src": String,
            #         "composition": String,
            #
            #         "frameStart": Number,
            #         "frameEnd": Number,
            #         "frameIncrement": Number,
            #
            #         "continueOnMissing": Boolean,
            #         "settingsTemplate": String,
            #         "outputModule": String,
            #         "outputExt": String,
            #     },
            #     "assets": [],
            #     "actions": {
            #         "prerender": [],
            #         "postrender": [],
            #     },
            #     "onChange": Function,
            #     "onRenderProgress": Function
            # }
            job = {'template':
                {
                    'src': 'file://' + self.input_path, 'composition': self.comp.replace('"', ''),
                    'settingsTemplate': self.render_settings.replace('"', ''),
                    'outputModule': self.omsettings.replace('"', ''), 'outputExt': 'mov'}
            }
            x = ['./nexrender-cli-macos', "'{}'".format(json.dumps(job))]
        else:
            logging.info('nexrender not found')
            x = [aerender_path(), '-project', self.input_path, '-comp', self.comp, '-RStemplate', self.render_settings,
                 '-OMtemplate', self.omsettings, '-output', self.output_path]
        return x

    def _parse_stdout(self, line):

        # print line
        if line.startswith('PROGRESS:'):
            # print 'progress'
            trimmed = line.replace('PROGRESS:', '').strip()
            if len(trimmed):
                self.progress_history.append(line)
                if 'Seconds' in trimmed:
                    self._update_progress(line)
                elif ': ' in trimmed:
                    tmp = trimmed.split(': ')
                    self.attributes[tmp[0].strip()] = tmp[1].strip()
        elif line.startswith('WARNING:'):
            trimmed = line.replace('WARNING:', '').strip()
            self.warnings.append(trimmed)
            logging.warning(trimmed)
        elif line.startswith('aerender ERROR') or 'ERROR:' in line:
            self.log_error(line)

    def _update_progress(self, line):

        if not self.total_frames:
            duration_string = self.attributes.get('Duration', None)
            frame_rate = self.attributes.get('Frame Rate', '0').split(' ')[0]
            self.total_frames = timecode_to_frames(duration_string.split('Duration:')[-1], float(frame_rate))

        match = re.match(r'PROGRESS:.*\((?P<frame>\d+)\): (?P<time>\d+)', line).groupdict()
        self.last_frame = match['frame']

    def average_frame_duration(self):

        total_durations = 0

        for line in self.progress_history:
            match = re.match(r'PROGRESS:.*\((?P<frame>\d+)\): (?P<time>\d+)', line)
            if match:
                total_durations += int(match.group(2))

        average = float(total_durations) / self.last_frame
        return average

    def percent_complete(self):
        if self.total_frames:
            return (float(self.last_frame) / float(self.total_frames)) * 100
        else:
            return 0


if __name__ == '__main__':
    logging.basicConfig(format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S', level=logging.DEBUG)

    r = AERenderWorker('/Users/brett/Desktop/Youtube_Vids/Film_Formats/Frame_Animations.aep', '"Film Pan"',
                   '"Draft Settings"', '"ProRes"', '/Users/brett/Desktop/test_render')
    r.start()
    while r.is_running():
        time.sleep(0.1)
