/*
 *      Copyright (c) 2015 Samsung Electronics Co., Ltd
 *
 *      Licensed under the Flora License, Version 1.1 (the "License");
 *      you may not use this file except in compliance with the License.
 *      You may obtain a copy of the License at
 *
 *              http://floralicense.org/license/
 *
 *      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.
 */

/*global define, document, tau*/

/**
 * Init main page module.
 *
 * @module views/main
 * @requires {@link helpers/constants}
 * @requires {@link helpers/grid}
 * @requires {@link helpers/line}
 * @requires {@link helpers/full}
 * @requires {@link helpers/select}
 * @requires {@link helpers/doubleClick}
 * @requires {@link helpers/longPress}
 * @requires {@link helpers/scroll}
 * @requires {@link views/zoom}
 * @namespace views/main
 */

define({
    name: 'views/main',
    requires: [
        'helpers/constants',
        'helpers/grid',
        'helpers/line',
        'helpers/full',
        'helpers/select',
        'helpers/doubleClick',
        'helpers/longPress',
        'helpers/scroll',
        'views/zoom'
    ],
    def: function viewsMain(req) {
        'use strict';

        /**
         * Constants helper module.
         *
         * @memberof views/main
         * @private
         * @type {Module}
         */
        var constants = req.helpers.constants,

            /**
             * Grid view helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            grid = req.helpers.grid,

            /**
             * Line view helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            line = req.helpers.line,

            /**
             * Full view helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            full = req.helpers.full,

            /**
             * Select overlay helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            select = req.helpers.select,

            /**
             * Double click helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            doubleClick = req.helpers.doubleClick,

            /**
             * Long press helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            longPress = req.helpers.longPress,

            /**
             * Scroll helper module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            scroll = req.helpers.scroll,

            /**
             * Zoom view module.
             *
             * @memberof views/main
             * @private
             * @type {Module}
             */
            zoom = req.views.zoom,

            /**
             * Class dictionary.
             *
             * @memberof views/main
             * @private
             * @const {Object}
             */
            CLASSES = Object.freeze({
                PICTURE: 'picture',
                PICTURE_GRID: 'picture-grid',
                PICTURE_LINE: 'picture-line',
                PICTURE_FULL: 'picture-full',
                PICTURE_WRAPPER: 'picture-wrapper',
                PICTURE_WRAPPER_GRID: 'picture-wrapper-grid',
                PICTURE_WRAPPER_LINE: 'picture-wrapper-line',
                PICTURE_WRAPPER_FULL: 'picture-wrapper-full',
                SCROLL_GRID: 'scroll-grid',
                SCROLL_LINE: 'scroll-line',
                SCROLL_FULL: 'scroll-full'
            }),

            /**
             * Id dictionary.
             *
             * @memberof views/main
             * @private
             * @const {Object}
             */
            ID = Object.freeze({
                PAGE: 'main',
                CONTENT: 'main-content',
                CONTAINER: 'main-container',
                EMPTY_PAGE: 'empty-page'
            }),

            /**
             * Direction dictionary.
             *
             * @memberof views/main
             * @private
             * @const {Object}
             */
            DIRECTION = Object.freeze({
                LEFT: 'CCW',
                RIGHT: 'CW'
            }),

            /**
             * Mock-up image list.
             *
             * @memberof views/main
             * @private
             * @const {string[]}
             */
            IMAGES = [
                'images/Default_image/gallery_default_image_01.jpg',
                'images/Default_image/gallery_default_image_02.jpg',
                'images/Default_image/gallery_default_image_03.jpg',
                'images/Default_image/gallery_default_image_04.jpg',
                'images/Default_image/gallery_default_image_05.jpg',
                'images/Default_image/gallery_default_image_06.jpg',
                'images/Default_image/gallery_default_image_07.jpg',
                'images/Default_image/gallery_default_image_08.jpg',
                'images/Default_image/gallery_default_image_09.jpg',
                'images/Default_image/gallery_default_image_10.jpg',
                'images/Default_image/gallery_default_image_11.jpg',
                'images/Default_image/gallery_default_image_12.jpg',
                'images/Default_image/gallery_default_image_13.JPG',
                'images/Default_image/gallery_default_image_14.JPG'
            ],

            /**
             * View helpers dictionary.
             *
             * @memberof views/main
             * @private
             * @type {object}
             */
            helpers = {},

            /**
             * Page element.
             *
             * @memberof views/main
             * @private
             * @type {HTMLElement}
             */
            page = null,

            /**
             * Content element.
             *
             * @memberof views/main
             * @private
             * @type {HTMLElement}
             */
            content = null,

            /**
             * Container element.
             *
             * @memberof views/main
             * @private
             * @type {HTMLElement}
             */
            container = null,

            /**
             * Current view mode.
             *
             * @memberof views/main
             * @private
             * @type {number}
             */
            currentMode = constants.MODE.GRID;

        /**
         * Returns current mode.
         *
         * @memberof views/main
         * @public
         * @returns {number}
         */
        function getCurrentMode() {
            return currentMode;
        }

        /**
         * Sets container with depending on current display mode.
         *
         * @memberof views/main
         * @private
         * @param {number} imageCount Images to display.
         */
        function setContainerWidth(imageCount) {
            var width = helpers[currentMode].getContainerWidth(imageCount);

            container.style.width = width + constants.PIXEL;
        }

        /**
         * Sets view mode.
         *
         * @memberof views/main
         * @private
         * @param {number} mode New display mode.
         */
        function setViewMode(mode) {
            var wrappers =
                    container.querySelectorAll('.' + CLASSES.PICTURE_WRAPPER),
                pictures = container.querySelectorAll('.' + CLASSES.PICTURE),
                len = wrappers.length,
                i = 0,
                position = {},
                picture = null,
                wrapper = null;

            setContainerWidth(len);

            for (i = 0; i < len; i += 1) {
                wrapper = wrappers[i];
                picture = pictures[i];

                content.classList.remove(
                    CLASSES.SCROLL_GRID,
                    CLASSES.SCROLL_LINE,
                    CLASSES.SCROLL_FULL
                );

                picture.classList.remove(
                    CLASSES.PICTURE_LINE,
                    CLASSES.PICTURE_FULL,
                    CLASSES.PICTURE_GRID
                );
                wrapper.classList.remove(
                    CLASSES.PICTURE_WRAPPER_LINE,
                    CLASSES.PICTURE_WRAPPER_FULL,
                    CLASSES.PICTURE_WRAPPER_GRID
                );

                switch (mode) {
                    case constants.MODE.GRID:
                        content.classList.add(CLASSES.SCROLL_GRID);
                        picture.classList.add(CLASSES.PICTURE_GRID);
                        wrapper.classList.add(CLASSES.PICTURE_WRAPPER_GRID);
                        break;
                    case constants.MODE.LINE:
                        content.classList.add(CLASSES.SCROLL_LINE);
                        picture.classList.add(CLASSES.PICTURE_LINE);
                        wrapper.classList.add(CLASSES.PICTURE_WRAPPER_LINE);
                        break;
                    case constants.MODE.FULL:
                        content.classList.add(CLASSES.SCROLL_FULL);
                        picture.classList.add(CLASSES.PICTURE_FULL);
                        wrapper.classList.add(CLASSES.PICTURE_WRAPPER_FULL);
                        break;
                }

                position = helpers[mode].getElementPosition(i);

                wrapper.style.top = position.top + constants.PIXEL;
                wrapper.style.left = position.left + constants.PIXEL;
            }
        }

        /**
         * Changes display mode.
         *
         * @memberof views/main
         * @public
         * @param {number} mode New display mode.
         * @param {number} id Id of element to handle.
         */
        function setDisplayMode(mode, id) {
            select.hideOverlay();
            switch (mode) {
                case constants.MODE.GRID:
                case constants.MODE.LINE:
                case constants.MODE.FULL:
                    currentMode = mode;
                    setViewMode(mode);
                    break;
                case constants.MODE.SELECT:
                    currentMode = mode;
                    setViewMode(constants.MODE.LINE);
                    select.showOverlay();
                    break;
                case constants.MODE.ZOOM:
                    zoom.setImage(IMAGES[id]);
                    tau.changePage('#zoom-page');
                    break;
            }
        }

        /**
         * Builds gallery from the picture list.
         *
         * @memberof views/main
         * @private
         * @param {string[]} imageList List of image paths.
         */
        function buildGallery(imageList) {
            var i = 0,
                len = imageList.length,
                imgElement = null,
                imgWrapper = null;

            for (i = 0; i < len; i += 1) {
                imgElement = document.createElement('img');
                imgElement.classList.add(CLASSES.PICTURE);
                imgElement.src = imageList[i];

                imgWrapper = document.createElement('div');
                imgWrapper.classList.add(CLASSES.PICTURE_WRAPPER);
                imgWrapper.id = i;

                imgWrapper.appendChild(imgElement);
                container.appendChild(imgWrapper);
            }

            setDisplayMode(constants.MODE.GRID, 0);
        }

        /**
         * Handles click event on container.
         *
         * @memberof views/main
         * @private
         * @param {Event} event Click event.
         */
        function onContainerClick(event) {
            var target = event.target,
                id = 0,
                elementScroll = 0,
                newMode = 0;

            if (target.classList.contains(CLASSES.PICTURE)) {
                id = Number(target.parentNode.id);
                newMode = helpers[currentMode].clickHandler(event);
                if (newMode !== null) {
                    setDisplayMode(newMode, id);
                    // center on selected picture
                    elementScroll = helpers[currentMode].getElementScroll(id);
                    scroll.scrollTo(content, elementScroll, 300);
                }
            }
        }

        /**
         * Handles long press event on container.
         *
         * @memberof views/main
         * @private
         * @param {Event} event Long press event.
         */
        function onContainerLongPress(event) {
            var target = event.target,
                id = 0,
                elementScroll = 0,
                newMode = 0;

            if (target.classList.contains(CLASSES.PICTURE)) {
                id = Number(target.parentNode.id);
                newMode = helpers[currentMode].longPressHandler(event);
                if (newMode !== null) {
                    setDisplayMode(newMode, id);
                    elementScroll = helpers[currentMode].getElementScroll(id);
                    scroll.scrollTo(content, elementScroll, 300);
                }
            }
        }

        /**
         * Handles double click event on container.
         *
         * @memberof views/main
         * @private
         * @param {Event} event Double click event.
         */
        function onContainerDoubleClick(event) {
            var target = event.target,
                id = 0,
                newMode = 0;

            if (target.classList.contains(CLASSES.PICTURE)) {
                id = Number(target.parentNode.id);
                newMode = helpers[currentMode].doubleClickHandler(event);
                if (newMode !== null) {
                    setDisplayMode(newMode, id);
                }
            }
        }

        /**
         * Rotary event handler.
         *
         * @memberof views/main
         * @private
         * @param {Event} event Rotary event.
         */
        function onRotaryEvent(event) {
            var direction = event.detail.direction,
                scrollTo = 0;

            if (direction === DIRECTION.RIGHT) {
                scrollTo = helpers[currentMode].getNextScroll(
                    content.scrollLeft,
                    container.style.width,
                    true
                );
            } else {
                scrollTo = helpers[currentMode].getNextScroll(
                    content.scrollLeft,
                    container.style.width,
                    false
                );
            }
            scroll.scrollTo(content, scrollTo, 300);
        }

        /**
         * Handles back event.
         *
         * @memberof views/main
         * @public
         */
        function onBack() {
            var newScroll = Math.floor((content.scrollLeft /
                            helpers[currentMode].getElementWidth()) / 3) *
                            constants.GRID_ELEMENT_WIDTH;

            setDisplayMode(constants.MODE.GRID);
            scroll.scrollTo(
                content,
                newScroll + constants.GRID_SECOND_LEFT,
                300
            );
        }

        /**
         * Registers event handlers.
         *
         * @memberof views/main
         * @private
         */
        function bindEvents() {
            container.addEventListener('click', onContainerClick);
            longPress.addHandler(container, onContainerLongPress);
            doubleClick.addHandler(container, onContainerDoubleClick);
            document.addEventListener('rotarydetent', onRotaryEvent);

            page.addEventListener('pagebeforeshow', function onShow() {
                document.addEventListener('rotarydetent', onRotaryEvent);
            });

            // Remove rotary event handler so it can be used on other pages
            // without breaking this one.
            page.addEventListener('pagebeforehide', function onHide() {
                document.removeEventListener('rotarydetent', onRotaryEvent);
            });
        }

        /**
         * Initializes the module.
         *
         * @memberof views/main
         * @public
         */
        function init() {
            helpers[constants.MODE.GRID] = grid;
            helpers[constants.MODE.LINE] = line;
            helpers[constants.MODE.FULL] = full;
            helpers[constants.MODE.SELECT] = select;

            page = document.getElementById(ID.PAGE);
            content = document.getElementById(ID.CONTENT);
            container = document.getElementById(ID.CONTAINER);

            bindEvents();

            if (IMAGES.length) {
                buildGallery(IMAGES);
            } else {
                tau.changePage(ID.EMPTY_PAGE);
            }
        }

        return {
            init: init,
            getCurrentMode: getCurrentMode,
            setDisplayMode: setDisplayMode,
            onBack: onBack
        };
    }

});
