/*
 * 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/camera-capture-view.h"
#include "../../common/inc/main-app.h"
#include "../../common/inc/list-popup.h"
#include "../../common/inc/radio-popup.h"
#include "../../common/inc/slider-popup.h"
#include "../../image/inc/capture-image-viewer.h"
#include "camera_recorder_settings.h"

#include <camera.h>
#include <Elementary.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <stdio.h>

#define BOX_PADDING 2
#define PREFIX_FILE_NAME "camera_capture"
#define STR_TITLE "Camera capture"
#define STR_CAPTURE "Capture"
#define STR_SETTINGS "Settings"
#define LABEL_LEN 64

typedef struct
{
    camera_capture_view *view;
    char *image_path;
} thumbnail_data;

typedef void (*process_func)(camera_capture_view *view, int val);

typedef enum
{
    ST_ZOOMLEVEL,
    ST_FRAMERATE,
    ST_PREVRESOLUTION,
    ST_CAPTRESOLUTION,
    ST_SCENEMODE,
    ST_EFFECT,
    ST_BRIGHTNESS,
    ST_ISOLEVEL,
    ST_WHITEBALANCE,
    ST_FOCUSMODE,
    ST_FLASHMODE,
    ST_EXPOSURE,
    ST_CAPTQUALITY,
    ST_MAX
}settings_type;

struct _camera_capture_view
{
    app_data *app;
    Elm_Object_Item *frame_item;
    Evas_Object *navi;
    Evas_Object *layout;
    Evas_Object *box;
    Evas_Object *toolbar;
    Evas_Object *camera_rect;
    Elm_Object_Item *seetings_btn;
    Elm_Object_Item *capture_btn;

    camera_h camera;

    unsigned int file_cnt;
    bool activated;

    char *image_path;

    Eina_List *resolution_list;
    settings_type setting_type;
    process_func popup_proc_func;
};

static const char * settings[ST_MAX] =
{
    "ZoomLevel",
    "Frame Rate",
    "Preview Resolution",
    "Capture Resolution",
    "Scene Mode",
    "Effect",
    "Brightness",
    "IsoLevel",
    "WhiteBalance",
    "Focus Mode",
    "Flash Mode",
    "Exposure",
    "Capture Quality"
};

static void _destroy(camera_capture_view *view);
static void _push(camera_capture_view *view);
static Evas_Object *_main_layout_add(camera_capture_view *view, Evas_Object *parent);
static Evas_Object *_toolbar_add(camera_capture_view *view, Evas_Object *parent);
static void _toolbar_btns_disabled(camera_capture_view *view, bool disabled);
static Evas_Object *_gallery_add(camera_capture_view *view, Evas_Object *parent);
static Evas_Object *_thumbnail_add(thumbnail_data *thumbnail);
static void _register_app_cbs(camera_capture_view *view);
static void _settigs_popup_show(camera_capture_view *view);

static char *_gen_file_name(camera_capture_view *view);
static char *_save_file(camera_capture_view *view, camera_image_data_s *image);

static void _pause(camera_capture_view *view);
static void _resume(camera_capture_view *view);

static void _capture(camera_capture_view *view);
static void _create_camera(camera_capture_view *view);
static void _destroy_camera(camera_capture_view *view);
static void _start_camera(camera_capture_view *view);
static void _stop_camera(camera_capture_view *view);

static void _on_capture_image_viewer_del_cb(void *user_data);
static void _on_camera_capture_completed_cb(void *user_data);
static void _on_camera_capture_cb(camera_image_data_s *image, camera_image_data_s *postview, camera_image_data_s *thumbnail, void *user_data);
static void _on_thumb_clicked_cb(void *data, Evas_Object *obj, void *event_info);
static void _on_resume_cb(void *user_data);
static void _on_pause_cb(void *user_data);
static void _on_settings_btn_pressed_cb(void *data, Evas_Object *obj, void *event_info);
static void _on_capture_btn_pressed_cb(void *data, Evas_Object *obj, void *event_info);
static void _on_main_layout_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _on_transition_finished(void *data, Evas_Object *obj, void *event_info);
static void _on_thumb_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _on_list_popup_closed_cb(list_popup *obj, bool result, void *user_data);
static void _on_list_popup_selected_item_cb(list_popup *obj, void *user_data);
static void _process_settings(camera_capture_view *view, settings_type type);
static void _create_zoom_settings(camera_capture_view *view);
static void _create_brightness_settings(camera_capture_view *view);
static void _create_resolution_settings(camera_capture_view *view);
static void _create_quality_settings(camera_capture_view *view);
static void _on_radio_popup_closed_cb(radio_popup *obj, bool result, void *user_data);
static void _on_slider_popup_closed_cb(slider_popup *obj, bool result, void *user_data);
static void _on_spec_settings_popup_selected_item_cb(radio_popup *obj, void *user_data);
static void _get_supported_resolution_list(camera_capture_view *view);
static void _get_current_resolution(camera_capture_view *view, int *widht, int *height);
static void _set_resolution(camera_capture_view *view, int widht, int height);
static void _destroy_supported_resolution_list(camera_capture_view *view);

camera_capture_view *camera_capture_view_add(app_data *app, Evas_Object *navi)
{
    if(!app)
    {
        return NULL;
    }

    camera_capture_view *view = calloc(1, sizeof(camera_capture_view));

    if(view)
    {
        view->navi = navi;
        view->app = app;
        view->layout = _main_layout_add(view, navi);
        view->activated = true;
        view->resolution_list = NULL;
        if(view->layout)
        {
            _register_app_cbs(view);
            evas_object_event_callback_add(view->layout, EVAS_CALLBACK_DEL, _on_main_layout_del_cb, view);
            _push(view);
        }
        else
        {
            _destroy(view);
            return NULL;
        }
    }

    return view;
}

static void _register_app_cbs(camera_capture_view *view)
{
    app_cbs cbs =
    {
       .pause = _on_pause_cb,
       .resume = _on_resume_cb,
    };

    app_set_cbs(view->app, cbs, view);
}

static void _pause(camera_capture_view *view)
{
    if(view->activated)
    {
        _stop_camera(view);
    }
}

static void _resume(camera_capture_view *view)
{
    if(view->activated)
    {
        _start_camera(view);
    }
}

static void _on_pause_cb(void *user_data)
{
    camera_capture_view *view = (camera_capture_view *)user_data;
    if(view)
    {
        _pause(view);
    }
}

static void _on_resume_cb(void *user_data)
{
    camera_capture_view *view = (camera_capture_view *)user_data;
    if(view)
    {
        _resume(view);
    }
}

static void _create_camera(camera_capture_view *view)
{
    if(view->camera)
    {
        _destroy_camera(view);
    }

    if(camera_create(CAMERA_DEVICE_CAMERA0, &view->camera) == CAMERA_ERROR_NONE)
    {
        camera_set_capture_format(view->camera, CAMERA_PIXEL_FORMAT_JPEG);
        camera_set_display(view->camera, CAMERA_DISPLAY_TYPE_EVAS, GET_DISPLAY(view->camera_rect));
        camera_set_display_mode(view->camera, CAMERA_DISPLAY_MODE_FULL);
        camera_set_display_rotation(view->camera, CAMERA_ROTATION_180);
        camera_set_display_flip(view->camera, CAMERA_FLIP_VERTICAL);
    }
    else
    {
        view->camera = NULL;
    }
}

static void _capture(camera_capture_view *view)
{
    int res = camera_start_capture(view->camera, _on_camera_capture_cb, _on_camera_capture_completed_cb, view);
    if(res == 0)
    {
        _toolbar_btns_disabled(view, true);
    }
}

static char *_gen_file_name(camera_capture_view *view)
{
    char buf[PATH_MAX] = {'\0'};
    snprintf(buf, PATH_MAX, PREFIX_FILE_NAME"%d.jpg", view->file_cnt);
    ++view->file_cnt;
    return gen_data_path(buf);
}

static char *_save_file(camera_capture_view *view, camera_image_data_s *image)
{
    char *file_name = _gen_file_name(view);

    FILE *f = fopen(file_name, "w");
    assert(f);

    if(f)
    {
        unsigned size = image->size ;
        unsigned char *data = image->data;

        while(size)
        {
           size_t written = fwrite(data, 1, size, f);
           size -= written;
           data += written;
        };

        fclose(f);
    }
    else
    {
        free(file_name);
        file_name = NULL;
    }

    return file_name;
}

static void _destroy_camera(camera_capture_view *view)
{
    if(view->camera)
    {
        camera_stop_preview(view->camera);
        camera_destroy(view->camera);
        view->camera = NULL;
    }
}

static void _start_camera(camera_capture_view *view)
{
    if(view->camera)
    {
        camera_start_preview(view->camera);
    }
}

static void _stop_camera(camera_capture_view *view)
{
    if(view->camera)
    {
        camera_stop_preview(view->camera);
    }
}

static void _destroy(camera_capture_view *view)
{
    app_reset_cbs(view->app);
    _destroy_camera(view);
    _destroy_supported_resolution_list(view);
    free(view);
}

static void _push(camera_capture_view *view)
{
    evas_object_smart_callback_add(view->navi, "transition,finished", _on_transition_finished, view);
    view->frame_item = elm_naviframe_item_push(view->navi, STR_TITLE, NULL, NULL, view->layout, NULL);
    view->toolbar = _toolbar_add(view, view->navi);
    elm_object_item_part_content_set(view->frame_item, "toolbar", view->toolbar);
}

static void _on_transition_finished(void *data, Evas_Object *obj, void *event_info)
{
    camera_capture_view *view = (camera_capture_view *)data;
    if(view)
    {
        _create_camera(view);
        _start_camera(view);
        evas_object_smart_callback_del(view->navi, "transition,finished", _on_transition_finished);
    }
}

static Evas_Object *_main_layout_add(camera_capture_view *view, Evas_Object *parent)
{
    Evas_Object *layout = elm_layout_add(parent);
    view->layout = layout;

    elm_layout_file_set(view->layout, CAMERACAPTUREEDJ, "camera_capture");
    evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
    evas_object_show(layout);

    Evas *evas = evas_object_evas_get(parent);
    view->camera_rect = evas_object_image_filled_add(evas);
    elm_object_part_content_set(layout, "render", view->camera_rect);

    Evas_Object *gallery = _gallery_add(view, layout);
    elm_object_part_content_set(layout, "gallery", gallery);

    return layout;
}

static Evas_Object *_gallery_add(camera_capture_view *view, Evas_Object *parent)
{
    Evas_Object *scr = elm_scroller_add(parent);
    elm_scroller_propagate_events_set(scr, true);
    evas_object_size_hint_weight_set(scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_show(scr);

    Evas_Object *box = elm_box_add(scr);
    elm_box_horizontal_set(box, EINA_TRUE);
    elm_box_homogeneous_set(box, EINA_TRUE);
    elm_box_padding_set(box, BOX_PADDING, BOX_PADDING);
    evas_object_show(box);

    elm_object_content_set(scr, box);

    view->box = box;
    return scr;
}

static Evas_Object *_thumbnail_add(thumbnail_data *thumbnail)
{
    int h = 0;
    evas_object_geometry_get(thumbnail->view->box, NULL, NULL, NULL, &h);

    Evas_Object *button = elm_button_add(thumbnail->view->box);
    evas_object_show(button);
    elm_object_style_set(button, "transparent");
    evas_object_size_hint_min_set(button, h, h);
    evas_object_size_hint_max_set(button, h, h);
    evas_object_smart_callback_add(button, "clicked", _on_thumb_clicked_cb, thumbnail);
    evas_object_event_callback_add(button, EVAS_CALLBACK_DEL, _on_thumb_del_cb, thumbnail);

    Evas_Object *image = elm_image_add(button);
    elm_image_file_set(image, thumbnail->image_path, NULL);
    elm_image_no_scale_set(image, EINA_FALSE);
    elm_image_resizable_set(image, EINA_TRUE, EINA_TRUE);
    elm_image_smooth_set(image, EINA_TRUE);
    elm_image_aspect_fixed_set(image, EINA_FALSE);
    elm_image_editable_set(image, EINA_FALSE);
    evas_object_show(image);
    evas_object_size_hint_min_set(image, h, h);
    evas_object_size_hint_max_set(image, h, h);

    elm_object_content_set(button, image);
    elm_box_pack_end(thumbnail->view->box, button);

    return button;
}

static Evas_Object *_toolbar_add(camera_capture_view *view, Evas_Object *parent)
{
    Evas_Object *toolbar = elm_toolbar_add(parent);

    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);
    evas_object_show(toolbar);

    elm_toolbar_select_mode_set(toolbar, ELM_OBJECT_SELECT_MODE_NONE);
    elm_toolbar_shrink_mode_set(toolbar, ELM_TOOLBAR_SHRINK_EXPAND);
    elm_toolbar_transverse_expanded_set(toolbar, EINA_TRUE);

    view->seetings_btn = elm_toolbar_item_append(toolbar, NULL, STR_SETTINGS, _on_settings_btn_pressed_cb, view);
    view->capture_btn = elm_toolbar_item_append(toolbar, NULL, STR_CAPTURE, _on_capture_btn_pressed_cb, view);

    return toolbar;
}

static void _settigs_popup_show(camera_capture_view *view)
{
    list_popup *popup = list_popup_add(view->app->win->win, ELM_POPUP_ORIENT_CENTER, STR_SETTINGS);
    list_popup_callback_set(popup, _on_list_popup_selected_item_cb, _on_list_popup_closed_cb, view);

    int i;
    for (i = 0; i<ST_MAX; i++)
    {
        list_popup_item_add(popup, settings[i], i);
    }
    list_popup_show(popup);
}

static void _toolbar_btns_disabled(camera_capture_view *view, bool disabled)
{
    elm_object_item_disabled_set(view->seetings_btn, disabled);
    elm_object_item_disabled_set(view->capture_btn, disabled);
}

static void _on_camera_capture_cb(camera_image_data_s *image, camera_image_data_s *postview, camera_image_data_s *thumbnail, void *user_data)
{
    camera_capture_view *view = user_data;

    if(view)
    {
        view->image_path = _save_file(view, image);
    }
}

static void _on_camera_capture_completed_cb(void *user_data)
{
    camera_capture_view *view = user_data;
    if(view)
    {
        camera_start_preview(view->camera);

        thumbnail_data *thumbnail = calloc(1, sizeof(thumbnail_data));
        thumbnail->view = view;
        thumbnail->image_path = view->image_path;
        _thumbnail_add(thumbnail);

        _toolbar_btns_disabled(thumbnail->view, false);
    }
}

static void _on_thumb_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
    thumbnail_data *thumbnail = data;
    if(thumbnail)
    {
        if(capture_image_viewer_add(thumbnail->view->app, thumbnail->view->navi, thumbnail->image_path,
                _on_capture_image_viewer_del_cb, thumbnail->view))
        {
            thumbnail->view->activated = false;
            _stop_camera(thumbnail->view);
        }
    }
}

static void _on_capture_image_viewer_del_cb(void *user_data)
{
    camera_capture_view *view = (camera_capture_view *)user_data;
    if(view)
    {
        view->activated = true;
        _start_camera(view);
    }
}

static void _on_settings_btn_pressed_cb(void *data, Evas_Object *obj, void *event_info)
{
    camera_capture_view *view = (camera_capture_view *)data;
    if(view)
    {
        _settigs_popup_show(view);
    }
}

static void _on_capture_btn_pressed_cb(void *data, Evas_Object *obj, void *event_info)
{
    camera_capture_view *view = (camera_capture_view *)data;
    if(view)
    {
        _capture(view);
    }
}

static void _on_thumb_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    thumbnail_data *thumbnail = data;
    if(thumbnail)
    {
        remove(thumbnail->image_path);
        free(thumbnail->image_path);
        free(thumbnail);
    }
}

static void _on_main_layout_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    camera_capture_view *view = (camera_capture_view *)data;
    if(view)
    {
        win_set_view_style(view->app->win, STYLE_DEFAULT_WINDOW);
        _destroy(view);
    }
}

static void _on_list_popup_selected_item_cb(list_popup *obj, void *user_data)
{
    camera_capture_view *view = user_data;
    int value = list_popup_selected_item_value_get(obj);
    _process_settings(view, value);
    list_popup_del(obj);
}

static void _on_radio_popup_closed_cb(radio_popup *obj, bool result, void *user_data)
{
    radio_popup_del(obj);
}

static void _on_list_popup_closed_cb(list_popup *obj, bool result, void *user_data)
{
    list_popup_del(obj);
}

static void _on_slider_popup_closed_cb(slider_popup *obj, bool result, void *user_data)
{
    slider_popup_del(obj);
}

static bool _settings_supported(int supported_type, void *user_data)
{
    settings_supported_data *supported_data = (settings_supported_data *)user_data;
    int i = camera_settings_item_number_get(supported_data, supported_type);
    supported_data->supported[i] = true;

    return true;
}

static void _create_spec_settings( camera_capture_view *view
                                 , const int max_type
                                 , const settings_data *data
                                 , void *media_device
                                 , register_supported_func supported_func)
{
    bool *supported = calloc(max_type, sizeof(bool));
    settings_supported_data supported_data;
    supported_data.data = data;
    supported_data.max_data_type = max_type;
    supported_data.supported = supported;

    radio_popup *popup = radio_popup_add(view->app->win->win, ELM_POPUP_ORIENT_BOTTOM, settings[view->setting_type]);
    radio_popup_callback_set(popup, _on_spec_settings_popup_selected_item_cb, _on_radio_popup_closed_cb, view);

    if(supported_func)
    {
        supported_func(media_device, _settings_supported, &supported_data);
    }

    Elm_Object_Item *item = NULL;
    int i;
    for(i = 0; i < max_type; i++)
    {
        item = radio_popup_item_add(popup, data[i].label, data[i].mode);
        if(supported_func && !supported[i] && i>0)
        {
            elm_object_item_disabled_set(item, EINA_TRUE);
        }
    }
    free(supported);
    radio_popup_select_item(popup, data[0].mode);
    radio_popup_show(popup);
}

static void _process_fps_settings(camera_capture_view *view, int val)
{
    camera_stop_preview(view->camera);
    int ret = camera_attr_set_preview_fps(view->camera, (camera_attr_fps_e)val);
    INF("Frame rate result = %d\n", ret);
    camera_start_preview(view->camera);
}

static void _process_scene_mode_settings(camera_capture_view *view, int val)
{
    camera_attr_set_scene_mode(view->camera, (camera_attr_scene_mode_e)val);
}

static void _process_effect_settings(camera_capture_view *view, int val)
{
    camera_attr_set_effect(view->camera, (camera_attr_effect_mode_e)val);
}

static void _process_iso_level_settings(camera_capture_view *view, int val)
{
    camera_attr_set_iso(view->camera, (camera_attr_iso_e)val);
}

static void _process_white_balance_settings(camera_capture_view *view, int val)
{
    camera_attr_set_whitebalance(view->camera, (camera_attr_whitebalance_e)val);
}

static void _process_focus_mode_settings(camera_capture_view *view, int val)
{
    camera_attr_set_af_mode(view->camera, (camera_attr_af_mode_e)val);
}

static void _process_flash_mode_settings(camera_capture_view *view, int val)
{
    camera_attr_set_flash_mode(view->camera, (camera_attr_flash_mode_e)val);
}

static void _process_exposure_mode_settings(camera_capture_view *view, int val)
{
    camera_attr_set_exposure_mode(view->camera, (camera_attr_exposure_mode_e)val);
}

static void _process_settings(camera_capture_view *view, settings_type type)
{
    int array_max = 0;
    const settings_data *data = NULL;
    void *media_device = view->camera;
    register_supported_func register_func = NULL;
    process_func proc_func = NULL;
    view->setting_type = type;
    switch(type)
    {
        case ST_ZOOMLEVEL:
            return _create_zoom_settings(view);
        break;
        case ST_FRAMERATE:
            array_max = fps_max_type;
            data = fps;
            register_func = (register_supported_func)camera_attr_foreach_supported_fps;
            proc_func = _process_fps_settings;
        break;
        case ST_PREVRESOLUTION:
            return _create_resolution_settings(view);
        break;
        case ST_CAPTRESOLUTION:
            return _create_resolution_settings(view);
        break;
        case ST_SCENEMODE:
            array_max = scene_mode_max_type;
            data = scene_mode;
            register_func = (register_supported_func)camera_attr_foreach_supported_scene_mode;
            proc_func = _process_scene_mode_settings;
        break;
        case ST_EFFECT:
            array_max = effect_max_type;
            data = effect;
            register_func = (register_supported_func)camera_attr_foreach_supported_effect;
            proc_func = _process_effect_settings;
        break;
        case ST_BRIGHTNESS:
            return _create_brightness_settings(view);
        break;
        case ST_ISOLEVEL:
            array_max = iso_level_max_type;
            data = iso_level;
            register_func = (register_supported_func)camera_attr_foreach_supported_iso;
            proc_func = _process_iso_level_settings;
        break;
        case ST_WHITEBALANCE:
            array_max = white_balance_max_type;
            data = white_balance;
            register_func = (register_supported_func)camera_attr_foreach_supported_whitebalance;
            proc_func = _process_white_balance_settings;
        break;
        case ST_FOCUSMODE:
            array_max = focus_mode_max;
            data = focus_mode;
            register_func = (register_supported_func)camera_attr_foreach_supported_af_mode;
            proc_func = _process_focus_mode_settings;
        break;
        case ST_FLASHMODE:
            array_max = flash_mode_max;
            data = flash_mode;
            register_func = (register_supported_func)camera_attr_foreach_supported_flash_mode;
            proc_func = _process_flash_mode_settings;
        break;
        case ST_EXPOSURE:
            array_max = exposure_mode_max_type;
            data = exposure_mode;
            register_func = (register_supported_func)camera_attr_foreach_supported_exposure_mode;
            proc_func = _process_exposure_mode_settings;
        break;
        case ST_CAPTQUALITY:
            return _create_quality_settings(view);
        break;
        default:
            return;
        break;
    }
    _create_spec_settings(view, array_max, data, media_device, register_func);
    view->popup_proc_func = proc_func;
}

static void _on_spec_settings_popup_selected_item_cb(radio_popup *obj, void *user_data)
{
    camera_capture_view *view = user_data;
    if(view->popup_proc_func)
    {
        int index = radio_popup_selected_item_value_get(obj);
        view->popup_proc_func(view, index);
    }
}

static void _slider_zoom_cb(slider_popup *popup, void *user_data)
{
    camera_capture_view *view = user_data;
    int value = slider_popup_value_get(popup);
    camera_attr_set_zoom(view->camera, value);
}

static void _create_zoom_settings(camera_capture_view *view)
{
    slider_popup *popup = slider_popup_add(view->app, view->app->win->win, ELM_POPUP_ORIENT_BOTTOM, settings[ST_ZOOMLEVEL]);
    slider_popup_label_set(popup, settings[ST_ZOOMLEVEL]);

    int max = 0;
    int min = 0;
    int level = 0;
    camera_attr_get_zoom_range(view->camera, &min, &max);
    slider_popup_min_max_set(popup, min, max);

    camera_attr_get_zoom(view->camera, &level);
    slider_popup_value_set(popup, level);

    slider_popup_callback_set(popup, _slider_zoom_cb, _on_slider_popup_closed_cb, view);
    slider_popup_show(popup);
}

static void _slider_brightness_cb(slider_popup *popup, void *user_data)
{
    camera_capture_view *view = user_data;
    int value = slider_popup_value_get(popup);
    camera_attr_set_brightness(view->camera, value);
}

static void _create_brightness_settings(camera_capture_view *view)
{
    slider_popup *popup = slider_popup_add(view->app, view->app->win->win, ELM_POPUP_ORIENT_BOTTOM, settings[ST_BRIGHTNESS]);
    slider_popup_label_set(popup, settings[ST_BRIGHTNESS]);

    int max = 0;
    int min = 0;
    int level = 0;
    camera_attr_get_brightness_range(view->camera, &min, &max);
    slider_popup_min_max_set(popup, min, max);

    camera_attr_get_brightness(view->camera, &level);
    slider_popup_value_set(popup, level);

    slider_popup_callback_set(popup, _slider_brightness_cb, _on_slider_popup_closed_cb, view);
    slider_popup_show(popup);
}

static bool _supported_resolution(int width, int height, void *user_data)
{
    camera_capture_view *view = (camera_capture_view *)user_data;
    resolution_item *item = calloc(1, sizeof(resolution_item));
    if(item)
    {
        item->width = width;
        item->height = height;
        view->resolution_list = eina_list_append(view->resolution_list, item);
    }

    return true;
}

static void _get_current_resolution(camera_capture_view *view, int *widht, int *height)
{
    switch (view->setting_type)
    {
        case ST_PREVRESOLUTION :
            camera_get_preview_resolution(view->camera, widht, height);
        break;
        case ST_CAPTRESOLUTION :
            camera_get_capture_resolution(view->camera, widht, height);
        break;
        default :
            return;
        break;
    }
}

static void _set_resolution(camera_capture_view *view, int widht, int height)
{
    switch (view->setting_type)
    {
        case ST_PREVRESOLUTION :
            camera_set_preview_resolution(view->camera, widht, height);
        break;
        case ST_CAPTRESOLUTION :
            camera_set_capture_resolution(view->camera, widht, height);
        break;
        default :
            return;
        break;
    }
}

static void _get_supported_resolution_list(camera_capture_view *view)
{
    _destroy_supported_resolution_list(view);
    if(!view->resolution_list)
    {
        switch (view->setting_type)
        {
            case ST_PREVRESOLUTION :
            case ST_CAPTRESOLUTION :
                camera_foreach_supported_preview_resolution(view->camera, _supported_resolution, view);
            break;
            default :
                _destroy_supported_resolution_list(view);
                return;
            break;
        }
    }
}

static void _destroy_supported_resolution_list(camera_capture_view *view)
{
    if(view->resolution_list)
    {
        resolution_item *item = NULL;
        EINA_LIST_FREE(view->resolution_list, item)
        {
            free(item);
        }
        view->resolution_list = NULL;
    }
}

static void _on_resolution_popup_selected_item_cb(radio_popup *obj, void *user_data)
{
    camera_capture_view *view = user_data;
    int index = radio_popup_selected_item_value_get(obj);
    resolution_item *item = (resolution_item *)eina_list_nth(view->resolution_list, index);
    camera_stop_preview(view->camera);
    _set_resolution(view, item->width, item->height);
    camera_start_preview(view->camera);
}

static void _create_resolution_settings(camera_capture_view *view)
{
    _get_supported_resolution_list(view);

    int current_width = 0;
    int current_height = 0;
    int currrent_resolution = -1;
    _get_current_resolution(view, &current_width, &current_height);

    char resol_name[LABEL_LEN] = {'\0'};

    radio_popup *popup = radio_popup_add(view->app->win->win, ELM_POPUP_ORIENT_BOTTOM, settings[view->setting_type]);
    radio_popup_callback_set(popup, _on_resolution_popup_selected_item_cb, _on_radio_popup_closed_cb, view);

    int index = 0;
    Eina_List *list = NULL;
    resolution_item *item = NULL;
    EINA_LIST_FOREACH(view->resolution_list, list, item)
    {
        if(currrent_resolution < 0 && current_width == item->width && current_height == item->height)
        {
            currrent_resolution = index;
        }
        snprintf(resol_name, LABEL_LEN, "%dx%d", item->width, item->height);
        radio_popup_item_add(popup, resol_name, index);
        index++;
    }

    radio_popup_select_item(popup, currrent_resolution);
    radio_popup_show(popup);
}

static void _slider_quality_cb(slider_popup *popup, void *user_data)
{
    camera_capture_view *view = user_data;
    int value = slider_popup_value_get(popup);
    camera_attr_set_image_quality(view->camera, value);
}

static void _create_quality_settings(camera_capture_view *view)
{
    slider_popup *popup = slider_popup_add(view->app, view->app->win->win, ELM_POPUP_ORIENT_BOTTOM, settings[ST_CAPTQUALITY]);
    slider_popup_label_set(popup, settings[ST_CAPTQUALITY]);

    slider_popup_min_max_set(popup, 0, 100);
    int level = 0;
    camera_attr_get_image_quality(view->camera, &level);
    slider_popup_value_set(popup, level);

    slider_popup_callback_set(popup, _slider_quality_cb, _on_slider_popup_closed_cb, view);
    slider_popup_show(popup);
}
