# -*- coding: utf-8 -*-

import argparse
from moviepy.editor import VideoFileClip, CompositeVideoClip
from moviepy.audio.fx import volumex
import os
from pprint import pprint
import subprocess
import sys

from lib.collection_utils import *
from lib.image_utils import *
from lib.io_utils import *
from lib.math_utils import *
from lib.processing_utils import *
from lib.video_utils import *

# input
parser = argparse.ArgumentParser()
parser.add_argument('-in', dest="INPUT_FILE", default="path/to/manifest.csv", help="Input csv instruction file")
parser.add_argument('-dir', dest="MEDIA_DIRECTORY", default="output/", help="Input markdown file")
parser.add_argument('-pad0', dest="PAD_START", default=2.0, type=float, help="Padding at start in s")
parser.add_argument('-pad1', dest="PAD_END", default=1.0, type=float, help="Padding at end in s")
parser.add_argument('-volume', dest="VOLUME", type=float, default=1.5, help="Adjust volume")
parser.add_argument('-out', dest="OUTPUT_FILE", default="output/trailer.mp4", help="Output media file")
parser.add_argument('-quality', dest="QUALITY", default="high", help="High quality is slower")
parser.add_argument('-probe', dest="PROBE", action="store_true", help="Just view statistics")
a = parser.parse_args()
aa = vars(a)

fieldNames, instructions = readCsv(a.INPUT_FILE)
makeDirectories([a.OUTPUT_FILE])

if len(instructions) <= 0:
    print("No instructions in %s" % a.INPUT_FILE)
    sys.exit()

instructions = prependAll(instructions, ("filename", a.MEDIA_DIRECTORY))
# instructions = instructions[:4]

# load videos
sequenceDur = 0
for i, step in enumerate(instructions):
    prev = False if i < 1 else instructions[i-1]

    # get duration from file
    if step["clip_dur"] < 0:
        instructions[i]["clip_dur"] = getDurationFromFile(step["filename"], accurate=True)
        step = instructions[i]

    # offset start if we are crossfading
    if step["crossfade"] > 0:
        instructions[i]["offset_start"] = -step["fade_in"]
        step = instructions[i]

    # inherit start from previous if not defined
    if step["clip_start"] < 0 and prev:
        instructions[i]["clip_start"] = prev["clip_start"] + prev["clip_dur"] + step["offset_start"]
        step = instructions[i]

    instructions[i]["start"] = a.PAD_START + sequenceDur + step["offset_start"]

    sequenceDur += step["offset_start"] + step["clip_dur"]

duration = a.PAD_START + sequenceDur + a.PAD_END
print("Total time: %s" % formatSeconds(duration))

# determine video properties from the first clip
testClip = VideoFileClip(instructions[0]["filename"])
width, height = testClip.size
fps = testClip.fps
# testClip = testClip.subclip(20, 6)
# testClip.reader.close()
# del testClip
print("Creating movie at %s x %s with %s fps" % (width, height, fps))

if a.PROBE:
    sys.exit()

clips = []
time = a.PAD_START
steps = len(instructions)
for i, step in enumerate(instructions):
    clip = VideoFileClip(step["filename"])
    vdur = clip.duration
    cstart = step["clip_start"]
    cdur = step["clip_dur"]
    if (cstart + cdur) > vdur:
        print("%s not long enough: %s > %s" % (step["filename"], (cstart + cdur), vdur))
        sys.exit()
    # make a clip if we are not taking the whole thing
    # print("%s, %s" % (step["clip_start"], step["clip_dur"]))
    if cstart > 0 or cdur < vdur:
        clip = clip.subclip(step["clip_start"], step["clip_start"]+step["clip_dur"])
    clip = clip.set_position((0, 0))
    clip = clip.set_start(step["start"])
    nextStep = False if i >= steps-1 else instructions[i+1]
    # cross fade in
    if step["crossfade"] > 0 and step["fade_in"] > 0:
        clip = clip.crossfadein(step["fade_in"])
    elif step["fade_in"] > 0:
        clip = clip.fadein(step["fade_in"])

    # cross fade out if next clip is cross fading in
    if nextStep and nextStep["crossfade"] > 0 and nextStep["fade_in"] > 0:
        clip = clip.crossfadeout(nextStep["fade_in"])
    elif step["fade_out"] > 0:
        clip = clip.fadeout(step["fade_out"])

    # fade in/out audio
    if step["fade_in"] > 0:
        clip = clip.audio_fadein(step["fade_in"])
    if step["fade_out"] > 0:
        clip = clip.audio_fadeout(step["fade_out"])

    clips.append(clip)
    printProgress(i+1, steps)

video = CompositeVideoClip(clips, size=(width, height))
video = video.set_duration(duration)
if a.VOLUME != 1.0:
    video = video.volumex(a.VOLUME)
if a.QUALITY == "high":
    video.write_videofile(a.OUTPUT_FILE, preset="slow", audio_bitrate="256k", audio_fps=48000, bitrate="19820k")
else:
    video.write_videofile(a.OUTPUT_FILE)
print("Wrote %s to file" % a.OUTPUT_FILE)
