/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 * Licensed 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 "../inc/frame-extractor.h"
#include "../../common/inc/logger.h"
#include "../inc/image-sample-utils.h"
#include <stdlib.h>
#include <metadata_extractor.h>
#include <image_util.h>

struct _frame_extractor
{
    metadata_extractor_h  metadata;

    int width;
    int height;
    int duration;
};

static int _frame_extractor_duration_get(const frame_extractor *extractor, int *duration);

static void _init_frame_data(frame_extractor *extractor)
{
    if(extractor)
    {
        char *width_value = NULL;
        char *height_value = NULL;
        int error = METADATA_EXTRACTOR_ERROR_NONE;
        error = metadata_extractor_get_metadata(extractor->metadata, METADATA_VIDEO_WIDTH, &width_value);
        if(METADATA_EXTRACTOR_ERROR_NONE == error && width_value)
        {
            extractor->width = atoi(width_value);
            free(width_value);
        }
        error = metadata_extractor_get_metadata(extractor->metadata, METADATA_VIDEO_HEIGHT, &height_value);
        if(METADATA_EXTRACTOR_ERROR_NONE == error && height_value)
        {
            extractor->height = atoi(height_value);
            free(height_value);
        }

        _frame_extractor_duration_get(extractor, &extractor->duration);
    }
}

frame_extractor *frame_extractor_create(const char *path_to_file)
{
    frame_extractor *result = NULL;

    RETVM_IF(!path_to_file, NULL, "Wrong input data");

    result = (frame_extractor *)malloc(sizeof(frame_extractor));

    if(result)
    {
        int error = METADATA_EXTRACTOR_ERROR_NONE;
        error = metadata_extractor_create(&result->metadata);
        if(METADATA_EXTRACTOR_ERROR_NONE != error)
        {
            free(result);
            return NULL;
        }
        error = metadata_extractor_set_path(result->metadata, path_to_file);
        if(METADATA_EXTRACTOR_ERROR_NONE != error)
        {
            metadata_extractor_destroy(result->metadata);
            free(result);
            return NULL;
        }
        _init_frame_data(result);
    }
    return result;
}

bool frame_extractor_change_file(frame_extractor *extractor, const char *path_to_file)
{
    RETVM_IF(!extractor || !path_to_file, NULL, "Wrong input data");

    int error = METADATA_EXTRACTOR_ERROR_NONE;

    error = metadata_extractor_set_path(extractor->metadata, path_to_file);
    if(METADATA_EXTRACTOR_ERROR_NONE != error)
    {
        return false;
    }
    _init_frame_data(extractor);

    return true;
}

void frame_extractor_destroy(frame_extractor *extractor)
{
    if(extractor)
    {
        metadata_extractor_destroy(extractor->metadata);
        free(extractor);
    }
}

void frame_extractor_size_get(const frame_extractor *extractor, int *width, int *height)
{
    if(extractor)
    {
        if(width)
        {
            *width = extractor->width;
        }
        if(height)
        {
            *height = extractor->height;
        }
    }
}

void frame_extractor_duration_get(const frame_extractor *extractor, int *duration)
{
    RETM_IF(!extractor || !duration, "Wrong input data");

    *duration = extractor->duration;
}

static int _frame_extractor_duration_get(const frame_extractor *extractor, int *duration)
{
    RETVM_IF(!extractor || !duration ||!extractor->metadata, -EINVAL, "Wrong input data");

    char *value = NULL;
    int error = metadata_extractor_get_metadata(extractor->metadata, METADATA_DURATION, &value);

    if(METADATA_EXTRACTOR_ERROR_NONE == error && value)
    {
        *duration = atoi(value);
        free(value);
    }

    return error;
}

bool frame_extractor_frame_get(const frame_extractor *extractor, unsigned char **frame, int pos)
{
    bool result = false;
    if(extractor && frame)
    {
        void * buf = NULL;
        int size = 0;
        int error = METADATA_EXTRACTOR_ERROR_NONE;
        error = metadata_extractor_get_frame_at_time(extractor->metadata, pos, false, &buf, &size);
        if(METADATA_EXTRACTOR_ERROR_NONE == error && buf)
        {
            *frame = malloc(size + (extractor->width * extractor->height) * ARGB_PIXEL_SIZE);
            if(*frame)
            {
                error = image_sample_util_convert_colorspace(*frame , IMAGE_UTIL_COLORSPACE_BGRA8888, buf,  extractor->width, extractor->height, IMAGE_UTIL_COLORSPACE_RGB888);
                if(IMAGE_UTIL_ERROR_NONE == error)
                {
                    result = true;
                }
                else
                {
                    free(*frame);
                    *frame = NULL;
                }
            }
            free(buf);
        }
    }

    return result;
}

