/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "avfcameradebug.h"
#include "avfmediarecordercontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include "avfaudioinputselectorcontrol.h"
#include "avfaudioencodersettingscontrol.h"
#include "avfvideoencodersettingscontrol.h"
#include "avfmediacontainercontrol.h"

#include <QtCore/qurl.h>
#include <QtCore/qfileinfo.h>
#include <QtMultimedia/qcameracontrol.h>


QT_USE_NAMESPACE

@interface AVFMediaRecorderDelegate : NSObject <AVCaptureFileOutputRecordingDelegate>
{
@private
    AVFMediaRecorderControl *m_recorder;
}

- (AVFMediaRecorderDelegate *) initWithRecorder:(AVFMediaRecorderControl*)recorder;

- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
         didStartRecordingToOutputFileAtURL:(NSURL *)fileURL
         fromConnections:(NSArray *)connections;

- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
         didFinishRecordingToOutputFileAtURL:(NSURL *)fileURL
         fromConnections:(NSArray *)connections
         error:(NSError *)error;
@end

@implementation AVFMediaRecorderDelegate

- (AVFMediaRecorderDelegate *) initWithRecorder:(AVFMediaRecorderControl*)recorder
{
    if (!(self = [super init]))
        return nil;

    self->m_recorder = recorder;
    return self;
}

- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
         didStartRecordingToOutputFileAtURL:(NSURL *)fileURL
         fromConnections:(NSArray *)connections
{
    Q_UNUSED(captureOutput);
    Q_UNUSED(fileURL);
    Q_UNUSED(connections)

    QMetaObject::invokeMethod(m_recorder, "handleRecordingStarted", Qt::QueuedConnection);
}

- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
         didFinishRecordingToOutputFileAtURL:(NSURL *)fileURL
         fromConnections:(NSArray *)connections
         error:(NSError *)error
{
    Q_UNUSED(captureOutput);
    Q_UNUSED(fileURL);
    Q_UNUSED(connections)

    if (error) {
        QStringList messageParts;
        messageParts << QString::fromUtf8([[error localizedDescription] UTF8String]);
        messageParts << QString::fromUtf8([[error localizedFailureReason] UTF8String]);
        messageParts << QString::fromUtf8([[error localizedRecoverySuggestion] UTF8String]);

        QString errorMessage = messageParts.join(" ");

        QMetaObject::invokeMethod(m_recorder, "handleRecordingFailed", Qt::QueuedConnection,
                                  Q_ARG(QString, errorMessage));
    } else {
        QMetaObject::invokeMethod(m_recorder, "handleRecordingFinished", Qt::QueuedConnection);
    }
}

@end


AVFMediaRecorderControl::AVFMediaRecorderControl(AVFCameraService *service, QObject *parent)
   : QMediaRecorderControl(parent)
   , m_service(service)
   , m_cameraControl(service->cameraControl())
   , m_audioInputControl(service->audioInputSelectorControl())
   , m_session(service->session())
   , m_connected(false)
   , m_state(QMediaRecorder::StoppedState)
   , m_lastStatus(QMediaRecorder::UnloadedStatus)
   , m_recordingStarted(false)
   , m_recordingFinished(false)
   , m_muted(false)
   , m_volume(1.0)
   , m_audioInput(nil)
   , m_restoreFPS(-1, -1)
{
    m_movieOutput = [[AVCaptureMovieFileOutput alloc] init];
    m_recorderDelagate = [[AVFMediaRecorderDelegate alloc] initWithRecorder:this];

    connect(m_cameraControl, SIGNAL(stateChanged(QCamera::State)), SLOT(updateStatus()));
    connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateStatus()));
    connect(m_cameraControl, SIGNAL(captureModeChanged(QCamera::CaptureModes)), SLOT(setupSessionForCapture()));
    connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(setupSessionForCapture()));
    connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(setupSessionForCapture()));
}

AVFMediaRecorderControl::~AVFMediaRecorderControl()
{
    if (m_movieOutput) {
        [m_session->captureSession() removeOutput:m_movieOutput];
        [m_movieOutput release];
    }

    if (m_audioInput) {
        [m_session->captureSession() removeInput:m_audioInput];
        [m_audioInput release];
    }

    [m_recorderDelagate release];
}

QUrl AVFMediaRecorderControl::outputLocation() const
{
    return m_outputLocation;
}

bool AVFMediaRecorderControl::setOutputLocation(const QUrl &location)
{
    m_outputLocation = location;
    return location.scheme() == QLatin1String("file") || location.scheme().isEmpty();
}

QMediaRecorder::State AVFMediaRecorderControl::state() const
{
    return m_state;
}

QMediaRecorder::Status AVFMediaRecorderControl::status() const
{
    QMediaRecorder::Status status = m_lastStatus;
    //bool videoEnabled = m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo);

    if (m_cameraControl->status() == QCamera::ActiveStatus && m_connected) {
        if (m_state == QMediaRecorder::StoppedState) {
            if (m_recordingStarted && !m_recordingFinished)
                status = QMediaRecorder::FinalizingStatus;
            else
                status = QMediaRecorder::LoadedStatus;
        } else {
            status = m_recordingStarted ? QMediaRecorder::RecordingStatus :
                                            QMediaRecorder::StartingStatus;
        }
    } else {
        //camera not started yet
        status = m_cameraControl->state() == QCamera::ActiveState && m_connected ?
                    QMediaRecorder::LoadingStatus:
                    QMediaRecorder::UnloadedStatus;
    }

    return status;
}

void AVFMediaRecorderControl::updateStatus()
{
    QMediaRecorder::Status newStatus = status();

    if (m_lastStatus != newStatus) {
        qDebugCamera() << "Camera recorder status changed: " << m_lastStatus << " -> " << newStatus;
        m_lastStatus = newStatus;
        Q_EMIT statusChanged(m_lastStatus);
    }
}


qint64 AVFMediaRecorderControl::duration() const
{
    if (!m_movieOutput)
        return 0;

    return qint64(CMTimeGetSeconds(m_movieOutput.recordedDuration) * 1000);
}

bool AVFMediaRecorderControl::isMuted() const
{
    return m_muted;
}

qreal AVFMediaRecorderControl::volume() const
{
    return m_volume;
}

void AVFMediaRecorderControl::applySettings()
{
    if (m_state != QMediaRecorder::StoppedState
            || (m_session->state() != QCamera::ActiveState && m_session->state() != QCamera::LoadedState)
            || !m_service->cameraControl()->captureMode().testFlag(QCamera::CaptureVideo)) {
        return;
    }

    // Configure audio settings
    [m_movieOutput setOutputSettings:m_service->audioEncoderSettingsControl()->applySettings()
                   forConnection:[m_movieOutput connectionWithMediaType:AVMediaTypeAudio]];

    // Configure video settings
    AVCaptureConnection *videoConnection = [m_movieOutput connectionWithMediaType:AVMediaTypeVideo];
    NSDictionary *videoSettings = m_service->videoEncoderSettingsControl()->applySettings(videoConnection);

    const AVFConfigurationLock lock(m_session->videoCaptureDevice()); // prevents activeFormat from being overridden

    [m_movieOutput setOutputSettings:videoSettings forConnection:videoConnection];
}

void AVFMediaRecorderControl::unapplySettings()
{
    m_service->audioEncoderSettingsControl()->unapplySettings();
    m_service->videoEncoderSettingsControl()->unapplySettings([m_movieOutput connectionWithMediaType:AVMediaTypeVideo]);
}

void AVFMediaRecorderControl::setState(QMediaRecorder::State state)
{
    if (m_state == state)
        return;

    qDebugCamera() << Q_FUNC_INFO << m_state << " -> " << state;

    switch (state) {
    case QMediaRecorder::RecordingState:
    {
        if (m_connected) {
            QString outputLocationPath = m_outputLocation.scheme() == QLatin1String("file") ?
                        m_outputLocation.path() : m_outputLocation.toString();

            QString extension = m_service->mediaContainerControl()->containerFormat();

            QUrl actualLocation = QUrl::fromLocalFile(
                        m_storageLocation.generateFileName(outputLocationPath,
                                                           QCamera::CaptureVideo,
                                                           QLatin1String("clip_"),
                                                           extension));

            qDebugCamera() << "Video capture location:" << actualLocation.toString();

            applySettings();

            [m_movieOutput startRecordingToOutputFileURL:actualLocation.toNSURL()
                           recordingDelegate:m_recorderDelagate];

            m_state = QMediaRecorder::RecordingState;
            m_recordingStarted = false;
            m_recordingFinished = false;

            Q_EMIT actualLocationChanged(actualLocation);
            updateStatus();
            Q_EMIT stateChanged(m_state);
        } else {
            Q_EMIT error(QMediaRecorder::FormatError, tr("Recorder not configured"));
        }

    } break;
    case QMediaRecorder::PausedState:
    {
        Q_EMIT error(QMediaRecorder::FormatError, tr("Recording pause not supported"));
        return;
    } break;
    case QMediaRecorder::StoppedState:
    {
        m_lastStatus = QMediaRecorder::FinalizingStatus;
        Q_EMIT statusChanged(m_lastStatus);
        [m_movieOutput stopRecording];
        unapplySettings();
    }
    }
}

void AVFMediaRecorderControl::setMuted(bool muted)
{
    if (m_muted != muted) {
        m_muted = muted;
        Q_EMIT mutedChanged(muted);
    }
}

void AVFMediaRecorderControl::setVolume(qreal volume)
{
    if (m_volume != volume) {
        m_volume = volume;
        Q_EMIT volumeChanged(volume);
    }
}

void AVFMediaRecorderControl::handleRecordingStarted()
{
    m_recordingStarted = true;
    updateStatus();
}

void AVFMediaRecorderControl::handleRecordingFinished()
{
    m_recordingFinished = true;
    if (m_state != QMediaRecorder::StoppedState) {
        m_state = QMediaRecorder::StoppedState;
        Q_EMIT stateChanged(m_state);
    }
    updateStatus();
}

void AVFMediaRecorderControl::handleRecordingFailed(const QString &message)
{
    m_recordingFinished = true;
    if (m_state != QMediaRecorder::StoppedState) {
        m_state = QMediaRecorder::StoppedState;
        Q_EMIT stateChanged(m_state);
    }
    updateStatus();

    Q_EMIT error(QMediaRecorder::ResourceError, message);
}

void AVFMediaRecorderControl::setupSessionForCapture()
{
    if (!m_session->videoCaptureDevice())
        return;

    //adding movie output causes high CPU usage even when while recording is not active,
    //connect it only while video capture mode is enabled.
    // Similarly, connect the Audio input only in that mode, since it's only necessary
    // when recording anyway. Adding an Audio input will trigger the microphone permission
    // request on iOS, but it shoudn't do so until we actually try to record.
    AVCaptureSession *captureSession = m_session->captureSession();

    if (!m_connected
            && m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo)
            && m_session->state() != QCamera::UnloadedState) {

        // Lock the video capture device to make sure the active format is not reset
        const AVFConfigurationLock lock(m_session->videoCaptureDevice());

        // Add audio input
        // Allow recording even if something wrong happens with the audio input initialization
        AVCaptureDevice *audioDevice = m_audioInputControl->createCaptureDevice();
        if (!audioDevice) {
            qWarning("No audio input device available");
        } else {
            NSError *error = nil;
            m_audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];

            if (!m_audioInput) {
                qWarning() << "Failed to create audio device input";
            } else if (![captureSession canAddInput:m_audioInput]) {
                qWarning() << "Could not connect the audio input";
                m_audioInput = nullptr;
            } else {
                [m_audioInput retain];
                [captureSession addInput:m_audioInput];
            }
        }

        if ([captureSession canAddOutput:m_movieOutput]) {
            [captureSession addOutput:m_movieOutput];
            m_connected = true;
        } else {
            Q_EMIT error(QMediaRecorder::ResourceError, tr("Could not connect the video recorder"));
            qWarning() << "Could not connect the video recorder";
        }
    } else if (m_connected
               && (!m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo)
                   || m_session->state() == QCamera::UnloadedState)) {

        // Lock the video capture device to make sure the active format is not reset
        const AVFConfigurationLock lock(m_session->videoCaptureDevice());

        [captureSession removeOutput:m_movieOutput];

        if (m_audioInput) {
            [captureSession removeInput:m_audioInput];
            [m_audioInput release];
            m_audioInput = nil;
        }

        m_connected = false;
    }

    updateStatus();
}

#include "moc_avfmediarecordercontrol.cpp"
