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

/*jslint devel: true*/
/*global $, tizen, app, Config, Helpers, Ui, Model, window */

var App = null;

(function strict() {
    'use strict';

    /**
     * Creates a new application object.
     *
     * @class Application
     */
    App = function App() {
        this.currentNumber = null;
        this.currentCaller = null;

        // RegExp for checking if the message contains only characters
        // from the GSM encoding set.
        this.gsmEncoding = new RegExp(
            '^[\\w@ZÄÖÑÜà£$¥èùìòÇØøÅåΔΦΓΛΩΠΨΣΘΞÆæßÉ' +
                '_ !#¤%&\\(\\)\\*=,-.\\\/:;<=>?' +
                '¡\\\'\\\"¿|^€{}\\[\\]~\\\n]*$',
            'i'
        );
        this.doubleChars = /[|\^€{}\[\]~]/g;
        this.notNumberChars = new RegExp('([^0-9+*#])', 'g');

        this.maxMessageLength = {'gsm': 160, 'utf': 70};
        this.totalMessageLength = {'gsm': 1530, 'utf': 670};
        this.multiMessageHeaderLength = {'gsm': 7, 'utf': 3};
        this.maxNumberOfMessages = {'gsm': 10, 'utf': 10};

        this.allowKeys = [8, 17, 37, 38, 39, 40, 46, 65, 187];
    };

    App.prototype = {
        /**
         * @type Array
         */
        requires: [
            'js/app.config.js',
            'js/app.helpers.js',
            'js/app.model.js',
            'js/app.ui.js',
            'js/app.ui.templateManager.js',
            'js/app.ui.templateManager.modifiers.js',
            'js/app.ui.events.js'
        ],

        /**
         * @type Model
         */
        model: null,

        /**
         * @type Ui
         */
        ui: null,

        /**
         * @type Config
         */
        config: null,

        /**
         * @type Helpers
         */
        helpers: null,

        /**
         * @type {string}
         */
        emulator_msg: 'Application works only on Target. ' +
            'Please run this on Target.',

        /**
         * Return true if device is supported for running application,
         * false otherwise.
         * @return {boolean}
         */
        isDeviceSupported: function isDeviceSupported() {
            return window.navigator.platform.indexOf('i686') === -1;
        },

        /**
         * Initializes App object.
         */
        init: function App_init() {
            if (!this.isDeviceSupported()) {
                window.alert(this.emulator_msg);
                this.exit();
            }

            this.config = new Config();
            this.helpers = new Helpers();
            this.ui = new Ui();
            this.model = new Model();
            return this;
        },

        /**
         * Sets current phone number.
         * @param {string} number
         */
        setCurrentNumber: function App_setCurrentNumber(number) {
            this.currentNumber = number;
        },

        /**
         * Returns current caller number string.
         * @return {number}
         */
        getCurrentNumber: function App_getCurrentNumber() {
            return this.currentNumber;
        },

        /**
         * Sets new current caller object.
         * @param {object} caller
         */
        setCurrentCaller: function App_setCurrentCaller(caller) {
            this.currentCaller = caller;
        },

        /**
         * Returns current caller object.
         * @return {object}
         */
        getCurrentCaller: function App_getCurrentCaller() {
            return this.currentCaller;
        },

        /**
         * Performs application exit action.
         */
        exit: function App_exit() {
            var application = tizen.application.getCurrentApplication();
            application.exit();
        },

        /**
         * Initializes content of current page.
         */
        fillUpMessagePage: function App_fillUpMessagePage() {
            var activePageId = $.mobile.activePage.attr('id');
            if (activePageId === 'main') {
                this.ui.loadCallerList();
            } else if (activePageId === 'contactSelect') {
                this.showContactsLoaded();
            } else {
                this.ui.showMessageChat();
            }
        },

        /**
         * Clears chat page elements to initial state.
         */
        resetPages: function App_resetPages() {
            this.ui.resetPages();
        },

        /**
         * Loads contacts.
         */
        loadContacts: function App_loadContacts() {
            this.model.loadContacts(this.showContactSelectPage.bind(this));
        },

        /**
         * Sorts loaded contacts and render contacts in the listview.
         */
        showContactsLoaded: function App_showContactsLoaded() {
            var i, len, sortedContactList = [];

            if (this.model.contactsLoaded !== null &&
                    this.model.contactsLoaded.length) {
                len = this.model.contactsLoaded.length;
                for (i = 0; i < len; i += 1) {
                    if (this.model.contactsLoaded[i].phoneNumbers.length) {
                        sortedContactList.push({
                            caller: this.helpers.getCallerName(
                                this.model.contactsLoaded[i],
                                'no name'
                            ),
                            number: this.model.contactsLoaded[i].primaryNumber,
                            contact: this.model.contactsLoaded[i]
                        });
                    }
                }

                sortedContactList.sort(function compareContacts(a, b) {
                    if (a.caller < b.caller) {
                        return -1;
                    }
                    if (a.caller > b.caller) {
                        return 1;
                    }
                    return 0;
                });
            }
            this.ui.fillContactList(sortedContactList);
        },

        /**
         * Shows contactSelect page.
         * It also resets currentCaller and currentNumber.
         */
        showContactSelectPage: function App_showContactSelectPage() {
            this.currentNumber = null;
            this.currentCaller = null;
            $.mobile.changePage('#contactSelect');
        },

        /**
         * Sends message to recipients.
         * @param {string} text Message body.
         * @param {array} numbers Array of message recipients.
         */
        sendMessage: function App_sendMessage(text, numbers) {
            var onError = function onError(e) {
                var message = 'Unknown error.';
                if (e) {
                    if (e.type === 'NetworkError') {
                        message = 'Network error.';
                    } else if (e.type === '') {
                        message = 'Invalid number.';
                    } else if (e.type) {
                        message = e.type;
                    } else if (e.message) {
                        message = e.message;
                    }
                }
                app.ui.showSendErrorPopup(message);
            };
            this.model.sendMessage(numbers, text,
                app.model.prepareMessages.bind(
                    app.model,
                    app.ui.showMessageChat
                ),
                onError
                );
        }
    };
}());
