/*
 * Copyright (c) 2012 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, tau*/

/**
 * Module main.
 */

define({
    name: 'views/main',
    requires: [
        'core/template',
        'models/calendar',
        'models/date',
        'models/filter',
        'views/edit'
    ],
    def: function viewsMain(req) {
        'use strict';

        /**
         * Template module object.
         * @type {Object}
         */
        var template = req.core.template,
            /**
             * Calendar module object.
             * @type {Object}
             */
            calendar = req.models.calendar,
            /**
             * Date module object.
             * @type {Object}
             */
            date = req.models.date,
            /**
             * Filter module object.
             * @type {Object}
             */
            filter = req.models.filter,
            /**
             * Event module object.
             * @type {Object}
             */
            edit = req.views.edit,
            /**
             * Event list.
             * @type {HTMLElement}
             */
            eventList = document.getElementById('event-list'),
            /**
             * Listener for calendar changes.
             * @type {object}
             */
            changeListener = null,

            /**
             * Found events.
             * @type {array}
             */
            eventArray = [],

            /**
             * Indicates whether the all day events were found already or not.
             * @type {boolean}
             */
            foundAllDayEventsComplete = false,

            /**
             * Indicates whether the normal events were found already or not.
             * @type {boolean}
             */
            foundNormalEventsComplete = false;

        /**
         * Creates a list of found events.
         */
        function recreateEventsList() {
            if (foundAllDayEventsComplete && foundNormalEventsComplete) {
                eventList.innerHTML = template.get('event', {arr: eventArray});
                tau.engine.createWidgets(eventList);
                tau.widget.Listview(eventList).refresh();
                eventArray = [];
                foundAllDayEventsComplete = false;
                foundNormalEventsComplete = false;
            }
        }

        /**
         * Handles success of event find operation.
         * Displays events on list.
         * @param {array} events Events to display
         */
        function onNormalEventsFound(events) {
            var i = 0,
                event = null,
                eventsLen = events.length;

            for (i = 0; i < eventsLen; i += 1) {
                event = events[i];
                if (event.isAllDay) {
                    continue;
                }
                eventArray.push({
                    id: event.id.uid,
                    summary: event.summary || '[No summary]',
                    allDay: event.isAllDay,
                    startDate: date.getDateString(event.startDate),
                    startTime: date.getTimeString(event.startDate),
                    endDate: date.getDateString(event.endDate),
                    endTime: date.getTimeString(event.endDate)
                });
            }
            foundNormalEventsComplete = true;
            recreateEventsList();
        }

        /**
         * Handles success of event find operation.
         * Displays events on list.
         * @param {array} events Events to display
         */
        function onAllDayEventsFound(events) {
            var i = 0,
                event = null,
                eventsLen = events.length;

            for (i = 0; i < eventsLen; i += 1) {
                event = events[i];
                if (!event.isAllDay) {
                    continue;
                }
                eventArray.push({
                    id: event.id.uid,
                    summary: event.summary || '[No summary]',
                    allDay: event.isAllDay,
                    startDate: date.getDateString(event.startDate),
                    startTime: date.getTimeString(event.startDate),
                    endDate: date.getDateString(event.endDate),
                    endTime: date.getTimeString(event.endDate)
                });
            }

            foundAllDayEventsComplete = true;
            recreateEventsList();
        }

        /**
         * Retrieves filtered events from calendar.
         */
        function getEvents() {
            var eventFilter = document.getElementById('event-filter');

            calendar.find(onNormalEventsFound,
                filter.getNormalEventsDateFilter(new Date(eventFilter.value)));

            calendar.find(onAllDayEventsFound,
                filter.getAllDayEventsDateFilter(new Date(eventFilter.value)));
        }

        /**
         * Handles new event button click.
         * Shows new event page.
         */
        function onNewEventClicked() {
            edit.show();
        }

        /**
         * Finds clicked list element with 'eventid' attribute.
         * @param {HTMLElement} element Child element clicked
         */
        function findClickedListElement(element) {
            var clickedLi = null;

            while (element) {
                if (element.dataset && element.dataset.eventid) {
                    clickedLi = element;
                    break;
                }
                element = element.parentNode;
            }

            return clickedLi;
        }

        /**
         * Handles click on list buttons.
         * @param {event} event
         */
        function onListElementClicked(event) {
            var target = event.target,
                item = findClickedListElement(target),
                eventId = 0;

            if (item) {
                eventId = item.dataset.eventid;
            }

            if (target.classList.contains('ui-btn-icon-rename') ||
                target.classList.contains('ui-icon-rename')) {
                edit.show(eventId);
            } else if (target.classList.contains('ui-btn-icon-delete') ||
                       target.classList.contains('ui-icon-delete')) {
                calendar.remove(eventId);
            }
        }

        /**
         * Binds events.
         */
        function bindEvents() {
            var newEventBtn = document.getElementById('new-event'),
                eventFilter = document.getElementById('event-filter');

            // TODO - clear this listener on app exit
            calendar.addChangeListener(changeListener);
            eventFilter.value = date.getDateString(new Date());
            eventFilter.addEventListener('input', getEvents);
            eventList.addEventListener('click', onListElementClicked);
            newEventBtn.addEventListener('click', onNewEventClicked);
        }

        /**
         * Initializes module.
         */
        function init() {
            changeListener = {
                /**
                 * Called when new items are added.
                 */
                onitemsadded: function onItemsAdded() {
                    getEvents();
                },
                /**
                 * Called when items are updated.
                 */
                onitemsupdated: function onItemsUpdated() {
                    getEvents();
                },
                /**
                 * Called when items are removed.
                 */
                onitemsremoved: function onItemsRemoved() {
                    getEvents();
                }
            };
            bindEvents();
            getEvents();
        }

        return {
            init: init
        };
    }
});
