/*
 * 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, tau, tizen, console, setTimeout*/
/*jshint maxparams:7*/

/**
 * Module calendar.
 */

define({
    name: 'models/calendar',
    requires: [
        'views/popup'
    ],
    def: function modelsCalendar(popup) {
        'use strict';

        /**
         * Variable holding reference to default calendar.
         * @type {tizen.Calendar}
         */
        var defaultCalendar = null;

        /**
         * Handles error callback.
         * @param {error} error Error object
         */
        function errorCallback(error) {
            // Needed because error is invoked before page change
            setTimeout(function onTimeout() {
                var pageId = tau.activePage.id;
                popup.show(pageId, error.name + ': ' + error.message);
            }, 100);
            console.error('Calendar error: ', error);
        }

        /**
         * Adds new event to default calendar.
         * @param {string} summary Event summary
         * @param {boolean} isAllDay Is event all day
         * @param {tizen.TZDate} startDate Event start date
         * @param {tizen.TZDate} endDate Event end date
         * @param {tizen.CalendarAlarm} alarm Event alarm
         * @returns {tizen.CalendarEvent} Created calendar event
         */
        function add(summary, isAllDay, startDate, endDate, alarm) {
            var item = null;
            try {
                item = new tizen.CalendarEvent({
                    summary: summary,
                    isAllDay: isAllDay,
                    startDate: startDate,
                    endDate: endDate,
                    alarms: alarm ? [alarm] : []
                });
                defaultCalendar.add(item);
                return item;
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Retrieves event with given id from calendar.
         * @param {number} id Event id
         * @returns {tizen.CalendarEvent} Event retrieved from calendar
         */
        function get(id) {
            try {
                return defaultCalendar.get(new tizen.CalendarEventId(id));
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Updates calendar event.
         * @param {number} id Id of event to update
         * @param {string} summary Event summary
         * @param {boolean} isAllDay Is event all day
         * @param {tizen.TZDate} startDate Event start date
         * @param {tizen.TZDate} endDate Event end date
         * @param {tizen.CalendarAlarm} alarm Event alarm
         */
        function update(id, summary, isAllDay, startDate, endDate, alarm) {
            var item = get(id);

            try {
                item.summary = summary;
                item.isAllDay = isAllDay;
                item.startDate = startDate;
                item.endDate = endDate;
                item.alarms = alarm ? [alarm] : [];
                defaultCalendar.update(item);
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Removes event with given id from calendar.
         * @param {number} id Event id
         */
        function remove(id) {
            try {
                defaultCalendar.remove(new tizen.CalendarEventId(id));
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Finds events in calendar by given filter.
         * @param {function} successCB Called when find returns data
         * @param {tizen.CompositeFilter} filter Filter for returned events
         */
        function find(successCB, filter) {
            var sortingMode = null;
            try {
                sortingMode = new tizen.SortMode('startDate', 'ASC');
                defaultCalendar.find(
                    successCB,
                    errorCallback,
                    filter,
                    sortingMode
                );
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Returns alarm object for given time duration.
         * @param {tizen.TimeDuration} timeDuration Time duration
         * @returns {tizen.CalendarAlarm} Created alarm
         */
        function createAlarm(timeDuration) {
            try {
                return new tizen.CalendarAlarm(
                    timeDuration,
                    'SOUND'
                );
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Adds callback for change listener.
         * @param {object} changeCallback
         * @returns {number} Listener id
         */
        function addChangeListener(changeCallback) {
            try {
                return defaultCalendar.addChangeListener(changeCallback);
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Removes change listener.
         * @param {number} listenerId
         */
        function removeChangeListener(listenerId) {
            try {
                defaultCalendar.removeChangeListener(listenerId);
            } catch (error) {
                errorCallback(error);
            }
        }

        /**
         * Initializes module.
         */
        function init() {
            try {
                defaultCalendar = tizen.calendar.getDefaultCalendar('EVENT');
            } catch (error) {
                errorCallback(error);
            }
        }

        return {
            init: init,
            add: add,
            get: get,
            update: update,
            remove: remove,
            find: find,
            createAlarm: createAlarm,
            addChangeListener: addChangeListener,
            removeChangeListener: removeChangeListener
        };
    }
});
