/*
 * 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 "config.h"
#include "../inc/frame-extractor-view.h"
#include "../inc/frame-extractor.h"
#include "../../common/inc/main-app.h"

#include <Elementary.h>

#define TEXT_SIZE 30

typedef enum
{
    VIEW_H264 = 0,
    VIEW_MPEG4,
    VIEW_MAX
} frame_extractor_view_type;

static const char *_files[VIEW_MAX] = { SAMPLEH264, SAMPLEMPEG4 };

struct _frame_extractor_view
{
    Elm_Object_Item *frame_item;
    Evas_Object *navi;
    Evas_Object *layout;
    Evas_Object *frame_image;
    Evas_Object *slider_bar;
    Evas_Object *info_label;
    Evas_Object *toolbar;

    Elm_Object_Item *prev_item;
    Elm_Object_Item *next_item;

    frame_extractor_view_type view_type;
    frame_extractor *extractor;

    app_data *app;
};

static Evas_Object *_add_main_layout(frame_extractor_view *extractor_view, Evas_Object *parent);
static Evas_Object *_add_frame_image(frame_extractor_view *extractor_view, Evas_Object *parent);
static Evas_Object *_add_slider_bar(Evas_Object *parent);
static Evas_Object *_add_text_info_label(Evas_Object *parent);
static Evas_Object *_add_toolbar(frame_extractor_view *extractor_view, Evas_Object *parent);
static void _push(frame_extractor_view *extractor_view);
static void _on_main_layout_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _update_view_type_controls(frame_extractor_view *extractor_view);
static void _update_view_title(frame_extractor_view *extractor_view);
static void _update_frame_view(frame_extractor_view *extractor_view);
static void _fill_text_info_label(frame_extractor_view *extractor_view);
static void _sliderbar_changed_cb(void *data, Evas_Object *obj, void *event_info);

frame_extractor_view *frame_extractor_view_add(app_data *app, Evas_Object *navi)
{
    frame_extractor_view *extractor_view = calloc(1, sizeof(frame_extractor_view));

    if(extractor_view)
    {
        extractor_view->navi = navi;
        extractor_view->app = app;
        extractor_view->view_type = VIEW_H264;
        extractor_view->extractor = frame_extractor_create(get_resource_path(_files[extractor_view->view_type]));
        extractor_view->layout = _add_main_layout(extractor_view, navi);

        if(extractor_view->layout)
        {
            evas_object_event_callback_add(extractor_view->layout, EVAS_CALLBACK_DEL, _on_main_layout_del_cb, extractor_view);
            extractor_view->frame_image = _add_frame_image(extractor_view, extractor_view->layout);
            _push(extractor_view);
            extractor_view->toolbar = _add_toolbar(extractor_view, navi);
            _update_view_type_controls(extractor_view);
            evas_object_smart_callback_add(extractor_view->slider_bar, "slider,drag,stop", _sliderbar_changed_cb, extractor_view);
            evas_object_smart_callback_add(extractor_view->slider_bar, "changed", _sliderbar_changed_cb, extractor_view);
            _update_view_title(extractor_view);
            _update_frame_view(extractor_view);

        }
        else
        {
            frame_extractor_destroy(extractor_view->extractor);
            free(extractor_view);
            return NULL;
        }
    }

    return extractor_view;
}

static Evas_Object *_add_slider_bar(Evas_Object *parent)
{
    Evas_Object *sliderbar = NULL;
    if(parent)
    {
        sliderbar = elm_slider_add(parent);
        elm_object_style_set(sliderbar, "list_progress");
        evas_object_size_hint_align_set(sliderbar, EVAS_HINT_FILL, 0.5);
        evas_object_size_hint_weight_set(sliderbar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
        elm_slider_value_set(sliderbar, 0.0);
        elm_slider_indicator_show_set(sliderbar, EINA_TRUE);
        elm_slider_indicator_format_set(sliderbar, " %.0f ");
        evas_object_show(sliderbar);
    }
    return sliderbar;
}

static Evas_Object *_add_text_info_label(Evas_Object *parent)
{
    Evas_Object *label = NULL;
    if(parent)
    {
        label = elm_label_add(parent);
        evas_object_show(label);
    }
    return label;
}

static Evas_Object *_add_main_layout(frame_extractor_view *extractor_view, Evas_Object *parent)
{
    Evas_Object *layout = elm_layout_add(parent);
    elm_layout_file_set(layout, FRAMEEXTRACTOREDJ, "frame_extractor_layout");
    evas_object_show(layout);
    extractor_view->slider_bar = _add_slider_bar(layout);
    elm_object_part_content_set(layout, "swallow.sliderbar", extractor_view->slider_bar);
    extractor_view->info_label = _add_text_info_label(layout);
    elm_object_part_content_set(layout, "swallow.info", extractor_view->info_label);

    _fill_text_info_label(extractor_view);

    return layout;
}

static void _fill_text_info_label(frame_extractor_view *extractor_view)
{
    RETM_IF(!extractor_view || !extractor_view->info_label || !extractor_view->extractor, "Wrong input data");

    char *base_file = (char *)get_resource_path(_files[extractor_view->view_type]);
    Eina_Strbuf *str_buffer = NULL;
    int width = 0;
    int height = 0;
    int duration = 0;

    frame_extractor_size_get(extractor_view->extractor, &width, &height);
    frame_extractor_duration_get(extractor_view->extractor, &duration);
    str_buffer = eina_strbuf_new();
    eina_strbuf_append(str_buffer, "<p>");
    eina_strbuf_append_printf(str_buffer, "%s<br>", basename(base_file));
    eina_strbuf_append_printf(str_buffer, "Dimension:%dx%d<br>", width, height);
    eina_strbuf_append_printf(str_buffer, "Duration:%d<br>", duration);
    eina_strbuf_append(str_buffer, "</p>");

    const char *buf = eina_strbuf_string_get(str_buffer);
    if(buf)
    {
        elm_object_text_set(extractor_view->info_label, buf);
    }
    eina_strbuf_free(str_buffer);
}

static Evas_Object *_add_frame_image(frame_extractor_view *extractor_view, Evas_Object *parent)
{
    RETVM_IF(!extractor_view || !parent, NULL, "Wrong input data");

    Evas *evas = evas_object_evas_get(parent);
    Evas_Object *image = evas_object_image_filled_add(evas);
    int width = 0;
    int height = 0;

    frame_extractor_size_get(extractor_view->extractor, &width, &height);
    evas_object_image_alpha_set(image, EINA_FALSE);
    evas_object_image_size_set(image, width , height);
    evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
    elm_object_part_content_set(parent, "swallow.visualization", image);
    evas_object_show(image);

    return image;
}

static void _prev(void *data, Evas_Object *obj, void *event_info)
{
    if(data)
    {
        frame_extractor_view *extractor_view = (frame_extractor_view *)data;

        extractor_view->view_type--;

        _update_view_type_controls(extractor_view);
        _update_view_title(extractor_view);
        _update_frame_view(extractor_view);
        _fill_text_info_label(extractor_view);
    }
}

static void _next(void *data, Evas_Object *obj, void *event_info)
{
    if(data)
    {
        frame_extractor_view *extractor_view = (frame_extractor_view *)data;
        frame_extractor_view_type type = extractor_view->view_type + 1;
        if(type < VIEW_MAX)
        {
            extractor_view->view_type++;
        }
        _update_view_type_controls(extractor_view);
        _update_view_title(extractor_view);
        _update_frame_view(extractor_view);
        _fill_text_info_label(extractor_view);
    }
}

static void _update_view_type_controls(frame_extractor_view *extractor_view)
{
    RETM_IF(!extractor_view, "Wrong input data");

    Eina_Bool prev_dis = extractor_view->view_type <= 0;
    Eina_Bool next_dis = extractor_view->view_type >= VIEW_MAX - 1;

    elm_object_item_disabled_set(extractor_view->prev_item, prev_dis);
    elm_object_item_disabled_set(extractor_view->next_item, next_dis);
}

static void _update_view_title(frame_extractor_view *extractor_view)
{
    Eina_Strbuf *buf = eina_strbuf_new();
    eina_strbuf_append_printf(buf, "Frame extractor(%d/%d)", (int)(extractor_view->view_type + 1), (int)(VIEW_MAX));
    const char *title = eina_strbuf_string_get(buf);
    elm_object_item_text_set(extractor_view->frame_item, title);
    eina_strbuf_free(buf);
}

static void _update_frame_view(frame_extractor_view *extractor_view)
{
    RETM_IF(!extractor_view, "Wrong input data");

    if(frame_extractor_change_file(extractor_view->extractor, get_resource_path(_files[extractor_view->view_type])))
    {
        int duration = 0;
        frame_extractor_duration_get(extractor_view->extractor, &duration);
        if(extractor_view->extractor && duration)
        {
            elm_slider_value_set(extractor_view->slider_bar, 0);
            evas_object_smart_callback_call(extractor_view->slider_bar, "slider,drag,stop", extractor_view);
            elm_slider_min_max_set(extractor_view->slider_bar, 0, (int)(duration/MILLISECONDS));
        }
    }
}

static Evas_Object *_add_toolbar(frame_extractor_view *extractor_view, Evas_Object *parent)
{
    RETVM_IF(!extractor_view || !parent, NULL, "Wrong input data");

    Evas_Object *toolbar = elm_toolbar_add(parent);
    elm_toolbar_shrink_mode_set(toolbar, ELM_TOOLBAR_SHRINK_EXPAND);
    elm_toolbar_transverse_expanded_set(toolbar, EINA_TRUE);
    elm_toolbar_select_mode_set(toolbar, ELM_OBJECT_SELECT_MODE_NONE);

    evas_object_size_hint_weight_set(toolbar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(toolbar, EVAS_HINT_FILL, EVAS_HINT_FILL);

    elm_object_item_part_content_set(extractor_view->frame_item, "toolbar", toolbar);

    extractor_view->prev_item = elm_toolbar_item_append(toolbar, NULL, "Prev", _prev, extractor_view);
    extractor_view->next_item = elm_toolbar_item_append(toolbar, NULL, "Next", _next, extractor_view);
    evas_object_show(toolbar);

    return toolbar;
}

static void _push(frame_extractor_view *extractor_view)
{
    extractor_view->frame_item = elm_naviframe_item_push(extractor_view->navi, NULL, NULL, NULL, extractor_view->layout, NULL);
}

static void _on_main_layout_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    if(data)
    {
        frame_extractor_view *extractor_view = (frame_extractor_view *)data;
        evas_object_image_data_set(extractor_view->frame_image, NULL);
        evas_object_del(extractor_view->frame_image);
        frame_extractor_destroy(extractor_view->extractor);
    }

    free(data);
}

static void _sliderbar_changed_cb(void *data, Evas_Object *obj, void *event_info)
{
    if(data)
    {
        frame_extractor_view *extractor_view = (frame_extractor_view *)data;
        unsigned char* frame = NULL;

        frame_extractor_frame_get(extractor_view->extractor, &frame, MILLISECONDS * elm_slider_value_get(extractor_view->slider_bar));
        if(frame)
        {
            evas_object_image_data_copy_set(extractor_view->frame_image, frame);
            free(frame);
        }
    }
}
