/*
 * 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.
 */

/* global define, document */

/**
 * Month page module.
 *
 * @requires {@link core/template}
 * @requires {@link models/date}
 * @requires {@link models/month}
 * @requires {@link helpers/date}
 * @namespace views/monthPage
 * @memberof views
 */

define({
    name: 'views/monthPage',
    requires: [
        'core/template',
        'models/date',
        'models/month',
        'helpers/date'
    ],
    def: function viewsMonthPage(req) {
        'use strict';

        /**
         * Core template module.
         *
         * @private
         * @type {Module}
         */
        var t = req.core.template,

            /**
             * Date helper module.
             *
             * @private
             * @type {Module}
             */
            d = req.helpers.date,

            /**
             * Month model module.
             *
             * @private
             * @type {Module}
             */
            month = req.models.month,

            /**
             * Date model module.
             *
             * @private
             * @type {Module}
             */
            dateModel = req.models.date,

            /**
             * CSS class name of the table element pointing on the current day.
             *
             * @private
             * @const {string}
             */
            DAY_TODAY_CLS = 'today',

            /**
             * Maximum number of rows in the month table.
             *
             * @private
             * @const {number}
             */
            ROWS_NUMBER = 6,

            /**
             * Reference to the page element.
             *
             * @private
             * @type {HTMLElement}
             */
            page = null,

            /**
             * Reference to the month table element.
             *
             * @private
             * @type {HTMLElement}
             */
            pageContent = null,

            /**
             * Reference to the page header element.
             *
             * @private
             * @type {HTMLElement}
             */
            monthHeader = null,

            /**
             * Reference to the page footer element.
             *
             * @private
             * @type {HTMLElement}
             */
            monthFooter = null,

            /**
             * Reference to the "Previous" button.
             *
             * @private
             * @type {HTMLElement}
             */
            prevBtn = null,

            /**
             * Reference to the "Current" button.
             *
             * @private
             * @type {HTMLElement}
             */
            currentBtn = null,

            /**
             * Reference to the "Next" button.
             *
             * @private
             * @type {HTMLElement}
             */
            nextBtn = null;

        /**
         * Push data to template and add it to page.
         *
         * @private
         * @param {array} data
         * @param {string} id
         */
        function addRow(data, id) {
            var row = t.get('monthRow', {
                days: data
            });

            document.getElementById(id + '-table').innerHTML += row;
        }

        /**
         * Adds empty row to month page.
         *
         * @private
         * @param {string} id
         */
        function addEmptyRow(id) {
            var row = t.get('emptyMonthRow');

            document.getElementById(id + '-table').innerHTML += row;
        }

        /**
         * Fills month grid.
         *
         * @private
         * @param {Date} date
         * @param {string} id
         */
        function fillTable(date, id) {
            var daysMatrix = month.getDaysMatrix(date),
                weeks = daysMatrix.length,
                i = 0,
                emptyRows = ROWS_NUMBER - weeks;

            for (i = 0; i < weeks; i += 1) {
                addRow(daysMatrix[i], id);
            }

            for (i = 0; i < emptyRows; i += 1) {
                addEmptyRow(id);
            }
        }

        /**
         * Sets page title with month and year.
         *
         * @private
         */
        function setHeader() {
            var date = dateModel.getCurrentDate();

            monthHeader.innerHTML = d.getMonthName(date) + ' ' +
                date.getFullYear();
        }


        /**
         * Adds month table template to body.
         *
         * @private
         */
        function prepareTables() {
            pageContent.innerHTML = t.get('monthTable', {id: 'month'});
        }

        /**
         * Adds class to day element.
         *
         * @private
         * @param {Date|string} date
         * @param {string} className
         */
        function markDay(date, className) {
            var dateString = typeof date === 'string' ?
                    date : d.toDataString(date),
                today = document.querySelector(
                    '[data-date="' + dateString + '"]'
                );

            if (today) {
                today.classList.add(className);
            }
        }

        /**
         * Fills tables with calendar data.
         *
         * @private
         */
        function fillTables() {
            var date = dateModel.getCurrentDate();
            fillTable(date, 'month');
        }

        /**
         * Creates calendar tables and events for month view.
         *
         * @private
         */
        function createView() {
            setHeader();
            prepareTables();
            fillTables();
            markDay(d.getCurrentDateTime(), DAY_TODAY_CLS);
        }

        /**
         * Shows previous month.
         *
         * @private
         */
        function showPrevMonth() {
            var currentDate = dateModel.getCurrentDate(),
                prevMonthDate = d.getPreviousMonth(currentDate);

            dateModel.setCurrentDate(prevMonthDate);
            createView();
        }

        /**
         * Shows next month.
         *
         * @private
         */
        function showNextMonth() {
            var currentDate = dateModel.getCurrentDate(),
                nextMonthDate = d.getNextMonth(currentDate);

            dateModel.setCurrentDate(nextMonthDate);
            createView();
        }

        /**
         * Handles click event on prevBtn button.
         *
         * @private
         */
        function onPrevMonthBtnTap() {
            showPrevMonth();
        }

        /**
         * Handles click event on nextBtn button.
         *
         * @private
         */
        function onNextMonthBtnTap() {
            showNextMonth();
        }

        /**
         * Handles click event on currentBtn button.
         *
         * @private
         */
        function onCurrentMonthBtnTap() {
            dateModel.setCurrentDate(d.getCurrentDateTime());
            createView();
        }

        /**
         * Shows main screen - month page.
         *
         * @private
         */
        function showMonthPage() {
            var pageHeight = page.offsetHeight,
                headerHeight = monthHeader.offsetHeight,
                footerHeight = monthFooter.offsetHeight,
                contentHeight = pageHeight - headerHeight - footerHeight;

            pageContent.style.height = contentHeight + 'px';
            page.classList.remove('invisible');
        }

        /**
         * Handles rotarydetent event on page element.
         *
         * @private
         * @param {event} ev
         */
        function onRotarydetent(ev) {
            var direction = ev.detail.direction;

            if (direction === 'CW') {
                showNextMonth();
            } else if (direction === 'CCW') {
                showPrevMonth();
            }
        }

        /**
         * Registers view event listeners.
         *
         * @private
         */
        function bindEvents() {
            prevBtn.addEventListener('click', onPrevMonthBtnTap);
            currentBtn.addEventListener('click', onCurrentMonthBtnTap);
            nextBtn.addEventListener('click', onNextMonthBtnTap);
        }

        /**
         * Initializes module.
         *
         * @memberof views/monthPage
         * @public
         */
        function init() {
            page = document.getElementById('month-page');
            page.addEventListener('rotarydetent', onRotarydetent);
            pageContent = document.getElementById('month-page-table-content');
            monthHeader = document.getElementById('month-header');
            monthFooter = document.getElementById('month-footer');
            prevBtn = document.getElementById('prev-month-btn');
            currentBtn = document.getElementById('current-month-btn');
            nextBtn = document.getElementById('next-month-btn');
            bindEvents();
            createView();
            showMonthPage();
        }

        return {
            init: init
        };
    }

});
