/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

#include "camera.h"
#include <cordova.h>

#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <QGraphicsObject>
#include <QCloseEvent>
#include <QQuickItem>

const char code[] = "\
var component, object;                                                  \
function createObject() {                                               \
    component = Qt.createComponent(%1);                                 \
    if (component.status == Component.Ready)                            \
        finishCreation();                                               \
    else                                                                \
        component.statusChanged.connect(finishCreation);                \
}                                                                       \
function finishCreation() {                                             \
    CordovaWrapper.global.cameraPluginWidget = component.createObject(root, \
        {root: root, cordova: cordova});                                \
}                                                                       \
createObject()";


Camera::Camera(Cordova *cordova):
    CPlugin(cordova),
    _lastScId(0),
    _lastEcId(0) {
}

bool Camera::preprocessImage(QString &path) {
    bool convertToPNG = (*_options.find("encodingType")).toInt() == Camera::PNG;
    int quality = (*_options.find("quality")).toInt();
    int width = (*_options.find("targetWidth")).toInt();
    int height = (*_options.find("targetHeight")).toInt();

    QImage image(path);
    if (width <= 0)
        width = image.width();
    if (height <= 0)
        height = image.height();
    image = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    QFile oldImage(path);
    QTemporaryFile newImage;

    const char *type;
    if (convertToPNG) {
        path = generateLocation("png");
        type = "png";
    } else {
        path = generateLocation("jpg");
        type = "jpg";
    }

    image.save(path, type, quality);

    oldImage.remove();

    return true;
}

void Camera::onImageSaved(QString path) {
    bool dataURL = _options.find("destinationType")->toInt() == Camera::DATA_URL;

    QString cbParams;
    if (preprocessImage(path)) {
        QString absolutePath = QFileInfo(path).absoluteFilePath();
        if (dataURL) {
            QFile image(absolutePath);
            image.open(QIODevice::ReadOnly);
            QByteArray content = image.readAll().toBase64();
            cbParams = QString("\"%1\"").arg(content.data());
            image.remove();
        } else {
            cbParams = CordovaInternal::format(QString("file://localhost") + absolutePath);
        }
    }

    this->callback(_lastScId, cbParams);

    _lastEcId = _lastScId = 0;
}

void Camera::takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
                         int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &/*popoverOptions*/, int/*cameraDirection*/) {
    if (_camera.isNull()) {
        _camera = QSharedPointer<QCamera>(new QCamera());
    }

    if (((_lastScId || _lastEcId) && (_lastScId != scId && _lastEcId != ecId)) || !_camera->isAvailable() || _camera->lockStatus() != QCamera::Unlocked) {
        this->cb(_lastEcId, "Device is busy");
        return;
    }

    _options.clear();
    _options.insert("quality", quality);
    _options.insert("destinationType", destinationType);
    _options.insert("targetWidth", targetWidth);
    _options.insert("targetHeight", targetHeight);
    _options.insert("encodingType", encodingType);

    _lastScId = scId;
    _lastEcId = ecId;

    QString path = m_cordova->get_app_dir() + "/../qml/CaptureWidget.qml";

    // TODO: relative url
    QString qml = QString(code).arg(CordovaInternal::format(path));
    m_cordova->execQML(qml);
}

void Camera::cancel() {
    m_cordova->execQML("CordovaWrapper.global.cameraPluginWidget.destroy()");
    this->cb(_lastEcId, "canceled");

    _lastEcId = _lastScId = 0;
}