import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import Qt.labs.settings 1.0
import Launcher 0.1
import FileUtils 1.0
import DataModel 1.0
import QtAVPlayerUtils 1.0

ColumnLayout {
    id: root

    signal commandExecutionStarted(var launcher);
    signal commandExecutionFinished(var results);

    property alias segmentDataView: segmentDataView
    property alias currentIndex: segmentDataView.currentIndex
    property alias rowFilter: segmentDataView.rowFilter
    property alias hoveredItem: segmentDataView.hoveredItem
    property int framesCount: 0
    property var extraOpts: ({})
    onExtraOptsChanged: {
        if(reportPath != '')
            applyButton.clicked();
    }

    signal clicked(var index, var item);
    signal doubleClicked(var index, var item);
    signal populated()

    property string reportPath
    property string videoPath
    property string outputPath
    property string pattern: patterns.currentText

    spacing: 0

    Rectangle {
        color: 'white'
        Layout.fillWidth: true
        Layout.minimumHeight: childrenRect.height

        Flow {
            id: segmentationOptionsLayout
            width: parent.width
            property bool needsApply: false;

            Label {
                text: "Segmenting Rules"
                font.bold: true
                verticalAlignment: Text.AlignVCenter
                height: recordingStartMarkers.implicitHeight
            }

            CheckBox {
                id: recordingStartMarkers
                text: "Rec Start Markers"
                onCheckedChanged: {
                    segmentationOptionsLayout.needsApply = true
                }
            }
            CheckBox {
                id: breaksInRecordingTime
                text: "Rec Time Break"
                onCheckedChanged: {
                    segmentationOptionsLayout.needsApply = true
                }
            }
            CheckBox {
                id: breaksInTimecode
                text: "Timecode Break"
                onCheckedChanged: {
                    segmentationOptionsLayout.needsApply = true
                }
            }
            CheckBox {
                id: segmentFilesToPreserveAudioSampleRate
                text: "Audio Setting Change"
                onCheckedChanged: {
                    segmentationOptionsLayout.needsApply = true
                }
            }

            Label {
                text: "Aspect Ratio Change"
                verticalAlignment: Text.AlignVCenter
                height: recordingStartMarkers.implicitHeight
                font.bold: true
            }

            ComboBoxEx {
                id: aspectRatiosSelector
                sizeToContents: true
                model: [
                    "Yes, segment frames by aspect ratio changes",
                    "No and use most common aspect ratio",
                    "No and force segments to use 4/3",
                    "No and force segments to use 16/9"
                ]
                onCurrentIndexChanged: {
                    segmentationOptionsLayout.needsApply = true
                }
            }

            ComboBoxEx {
                id: patterns
                sizeToContents: true
                Layout.minimumWidth: modelWidth + 2*leftPadding + 2*rightPadding
                model: [
                    "%FILENAME%_part%PARTNO%",
                    "%FILENAME%_%RECDATE%_%RECTIME%",
                    "%FILENAME%_%PARTNO%_%TC%",
                    "%FILENAME%_%RECDATE%-%RECTIME%_%TC%"
                ]
                onCurrentIndexChanged: {
                    segmentationOptionsLayout.needsApply = true
                }
            }

            Button {
                text: "Reset"
                onClicked: {
                    if(recordingStartMarkers.checked) {
                        recordingStartMarkers.checked = false
                        segmentationOptionsLayout.needsApply = true
                    }

                    if(breaksInRecordingTime.checked) {
                        breaksInRecordingTime.checked = false
                        segmentationOptionsLayout.needsApply = true
                    }

                    if(breaksInTimecode.checked) {
                        breaksInTimecode.checked = false
                        segmentationOptionsLayout.needsApply = true
                    }

                    if(segmentFilesToPreserveAudioSampleRate.checked) {
                        segmentFilesToPreserveAudioSampleRate.checked = false
                        segmentationOptionsLayout.needsApply = true
                    }

                    if(aspectRatiosSelector.currentIndex !== 0) {
                        aspectRatiosSelector.currentIndex = 0
                        segmentationOptionsLayout.needsApply = true
                    }
                }
            }

            Button {
                id: applyButton
                enabled: segmentationOptionsLayout.needsApply
                text: "Apply"
                onClicked: {
                    segmentDataView.populateSegmentData(reportPath, videoPath, outputPath, extraOpts)
                    segmentationOptionsLayout.needsApply = false
                }
            }
        }
    }

    Text {
        id: label
        text: 'SEGMENTATION RULES'
        color: 'white'
        font.pixelSize: 20
    }

    SegmentDataView {
        id: segmentDataView
        Layout.fillWidth: true
        Layout.fillHeight: true
        total: framesCount

        signal populated();

        onPopulated: {
            root.populated();
        }

        Component.onCompleted: {
            var e = {
                'Segment #' : '',
                'Frame #' : '',
                'Timestamp' : '',
                'Timecode' : '',
                'Timecode: Jump/Repeat' : Qt.point(0, 0),
                'Recording Time' : '',
                'Recording Time: Jump/Repeat' : Qt.point(0, 0),
                'Recording Marks' : Qt.point(0, 0),
                'Video/Audio' : '',
                'Filename Pattern' : ''
            }

            segmentDataView.model.appendRow(e);
            segmentDataView.model.clear();
        }

        SegmentDataParser {
            id: segmentDataParser
        }

        function packaging(reportPath, videoPath, outputDir, extraOpts, onOutputChanged) {

            if(outputDir === '') {
                outputDir = FileUtils.getFileDir(reportPath);
            }

            if(Qt.platform.os === "windows") {
                reportPath = "/cygdrive/" + reportPath.replace(":", "");
                videoPath = "/cygdrive/" + videoPath.replace(":", "");
                outputDir = "/cygdrive/" + outputDir.replace(":", "");
            }

            console.debug('packaging: reportPath = ', reportPath, 'videoPath = ', videoPath, 'outputDir = ', outputDir)

            var extraParams = ['-v']
            extraParams.push(...['-X', packagerCtl.effectiveXmlStarletCmd])
            extraParams.push(...['-F',  packagerCtl.effectiveFfmpegCmd])
            extraParams.push(...['-D', packagerCtl.effectiveDvrescueCmd])
            extraParams.push(...['-M', packagerCtl.effectiveMediaInfoCmd])

            var opts = ['-z'];
            if(recordingStartMarkers.checked)
                opts.push('-s')
            if(breaksInRecordingTime.checked)
                opts.push('-d');
            if(breaksInTimecode.checked)
                opts.push('-t');
            if(segmentFilesToPreserveAudioSampleRate.checked)
                opts.push('-3');

            if(aspectRatiosSelector.currentIndex === 0)
                opts.push(...['-a', 'n']);
            if(aspectRatiosSelector.currentIndex === 2)
                opts.push(...['-a', '4']);
            if(aspectRatiosSelector.currentIndex === 3)
                opts.push(...['-a', '9']);
            if(aspectRatiosSelector.currentIndex === 1)
                opts.push(...['-a', 'c']);

            if(extraOpts && extraOpts.type === 'mkv')
                opts.push(...['-e', 'mkv']);

            opts.push(...['-o', outputDir]);
            opts.push(...['-x', reportPath, videoPath]);

            var output = '';
            return packagerCtl.exec(opts, (launcher) => {
                                 commandExecutionStarted(launcher)
                                 launcher.outputChanged.connect((outputString) => {
                                                                    if(onOutputChanged)
                                                                        onOutputChanged(outputString);
                                                                    output += outputString;
                                                                })

                                 launcher.errorChanged.connect((errorString) => {
                                                                    if(onOutputChanged)
                                                                        onOutputChanged(errorString);
                                                                    commandExecutionFinished(errorString);
                                                               })
                             }, extraParams).then(() => {
                                                      console.debug('executed packagerCtl....')
                                                      commandExecutionFinished(output);
                                                  });
        }

        function populateSegmentData(reportPath, videoPath, outputPath, extraOpts) {
            console.debug('populateSegmentData: reportPath = ', reportPath, 'videoPath = ', videoPath, 'outputPath = ', outputPath)

            segmentDataView.model.clear();

            if(Qt.platform.os === "windows") {
                reportPath = "/cygdrive/" + reportPath.replace(":", "");
                videoPath = "/cygdrive/" + videoPath.replace(":", "");
            }

            var extraParams = ['-v', '-X', packagerCtl.effectiveXmlStarletCmd, '-O', pattern]
            var opts = [];
            if(recordingStartMarkers.checked)
                opts.push('-s')
            if(breaksInRecordingTime.checked)
                opts.push('-d');
            if(breaksInTimecode.checked)
                opts.push('-t');
            if(segmentFilesToPreserveAudioSampleRate.checked)
                opts.push('-3');

            if(aspectRatiosSelector.currentIndex === 0)
                opts.push(...['-a', 'n']);
            if(aspectRatiosSelector.currentIndex === 2)
                opts.push(...['-a', '4']);
            if(aspectRatiosSelector.currentIndex === 3)
                opts.push(...['-a', '9']);
            if(aspectRatiosSelector.currentIndex === 1)
                opts.push(...['-a', 'c']);

            if(extraOpts && extraOpts.type === 'mkv')
                opts.push(...['-e', 'mkv']);

            if(outputPath) {
                if(Qt.platform.os === "windows") {
                    outputPath = "/cygdrive/" + outputPath.replace(":", "");
                }
                opts.push(...['-o', outputPath]);
            }

            opts.push(...['-T', reportPath, videoPath])

            var output = '';
            packagerCtl.exec(opts, (launcher) => {
                                 commandExecutionStarted(launcher)
                                 launcher.outputChanged.connect((outputString) => {
                                                                    output += outputString;
                                                                })
                             }, extraParams).then(() => {
                                                      console.debug('executed....')
                                                      commandExecutionFinished(output);

                                                      var i = 0;
                                                      segmentDataParser.parse(output, (entry) => {
                                                                                  console.debug('entry: ', JSON.stringify(entry));

                                                                                  var videoAudio = [
                                                                                      entry.frameSize,
                                                                                      entry.frameRate,
                                                                                      entry.chromaSubsampling,
                                                                                      entry.aspectRatio,
                                                                                      entry.samplingRate,
                                                                                      entry.channelCount
                                                                                  ]

                                                                                  ++i
                                                                                  var e = {
                                                                                      'Segment #' : i,
                                                                                      'Frame #' : entry.startFrame,
                                                                                      'Timestamp' : entry.startPts,
                                                                                      'Timecode' : entry.timeCode,
                                                                                      'Timecode: Jump/Repeat' : Qt.point(entry.timeCodeJump, 0),
                                                                                      'Recording Time' : entry.recTimestamp,
                                                                                      'Recording Time: Jump/Repeat' : Qt.point(entry.recTimeJump, 0),
                                                                                      'Recording Marks' : Qt.point(entry.recStart, 0),
                                                                                      'Video/Audio' : videoAudio.join(' '),
                                                                                      'FileName' : entry.segmentFileName ? entry.segmentFileName : i,
                                                                                      'Filename Pattern' : entry.segmentFileName ? entry.segmentFileName : i
                                                                                  }

                                                                                  if(Qt.platform.os === "windows") {
                                                                                      var cygwinPath = e.FileName;
                                                                                      var splittedWinPath = cygwinPath.replace('/cygdrive/', '').split('/')
                                                                                      if(splittedWinPath.length !== 0) {
                                                                                        splittedWinPath[0] = splittedWinPath[0] + ':'
                                                                                        e.FileName = splittedWinPath.join('\\')
                                                                                        e['Filename Pattern'] = e.FileName
                                                                                      }
                                                                                  }

                                                                                  segmentDataView.model.appendRow(e);
                                                                              });
                                                      segmentDataView.populated();
                                                      busy.running = false;
                                                  }).catch((error) => {
                                                               commandExecutionFinished(error);
                                                               segmentDataView.populated();
                                                               busy.running = false;
                                                        });
        }
    }
}
