/*
 * 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 $, tizen, Config, localStorage, setTimeout, document, alert, console */

var App = null,
    app = null; // App instance

(function strict() { // strict mode wrapper
    'use strict';

    /**
     * Creates a new application object.
     *
     * @class Application
     */
    App = function App() {};

    App.prototype = {
        nfcAdapter: null,
        addressBook: null,
        started: false,
        timeOutHandler: null,
        counterState: true,
        nfc: null,

        /**
         * Initializes application.
         */
        init: function appInit() {
            this.config = new Config();
            this.ui = new App.Ui(this);
            this.nfc = new App.NFCControl(this);
            this.ui.defineEvents();
            this.initAddressBook(this.nfc.startNFC.bind(this.nfc));
        },

        /**
         * Saves default contact to localStorage.
         */
        saveDefaultCard: function saveDefaultCard() {
            var elementSelected = $('#list-choose li.selected');
            localStorage.started = true;
            localStorage.id = elementSelected.data('id');
            localStorage.caller = elementSelected.data('caller');
            localStorage.firstName = elementSelected.data('firstName');
            localStorage.middleName = elementSelected.data('middleName');
            localStorage.lastName = elementSelected.data('lastName');
            localStorage.phoneNumber = elementSelected.data('phoneNumber');
            localStorage.vCard = elementSelected.data('vCard');
            this.started = true;

            $.mobile.changePage('#start');
        },

        /**
         * Updates default contact in localStorage.
         * @param {Contact} contact
         */
        updateDefaultCard: function updateDefaultCard(contact) {
            localStorage.caller = this.ui.prepareCallerName(contact);
            localStorage.firstName = contact.name.firstName || '';
            localStorage.middleName = contact.name.middleName || '';
            localStorage.lastName = contact.name.lastName || '';
            localStorage.phoneNumber = contact.phoneNumbers[0].number;
            localStorage.id = contact.id;
            localStorage.vCard = contact.convertToString('VCARD_30');
        },

        /**
         * Performs action on getAddressBooks success.
         * @param {AddressBook[]} addressbooks
         */
        getAddressBooksSuccess: function getAddressBooksSuccess(addressbooks) {
            if (addressbooks.length > 0) {
                var self = this,
                    resetLocalSorage = function onStorageReset() {
                        // Reset localStorage
                        localStorage.clear();
                        self.started = false;

                        // Load start page with temporary content
                        self.ui.moveToStartPage();
                        self.ui.loadTemporaryContent();
                    };
                this.addressBook = addressbooks[0];

                if (localStorage.id) {
                    try {
                        this.updateDefaultCard(
                            this.addressBook.get(localStorage.id)
                        );
                    } catch (err) {
                        if (err.name === 'NotFoundError') {
                            resetLocalSorage();
                        }
                    }
                }

                // Registers to be notified when the address book changes
                this.addressBook.addChangeListener({
                    oncontactsadded: function onContactsAdded(contacts) {
                        // Refresh if choose page active
                        self.ui.refreshIfActivePage('choose');
                    },
                    oncontactsremoved: function onContactsRemoved(ids) {
                        // Refresh localStorage if default contact was deleted
                        if (ids.indexOf(localStorage.id) >= 0) {
                            resetLocalSorage();
                            alert('Your default contact has been removed. ' +
                                'Please choose another one.');
                        } else {
                            // Refresh if choose page active
                            self.ui.refreshIfActivePage('choose');
                        }
                    },
                    oncontactsupdated: function onContactsUpdated(contacts) {
                        var index = contacts.length;

                        // check if default contact was updated
                        while (index - 1) {
                            if (contacts[index].id === localStorage.id) {
                                try {
                                    self.updateDefaultCard(contacts[index]);
                                } catch (e) {
                                    resetLocalSorage();
                                    alert('That contact is no longer valid. ' +
                                        'Choose another one.');
                                } finally {
                                    break;
                                }
                            }
                            index -= 1;
                        }

                        self.ui.refreshIfActivePage('start');
                    }
                });
            } else {
                console.error('initAddressBook failed');
            }
        },

        /**
         * Performs action on getAddressBooks error.
         * @param {error} e
         */
        getAddressBooksError: function getAddressBooksError(e) {
            console.error('getAddressBooks() error: ' + e.message);
        },

        /**
         * Initializes address book.
         * @param {function} callback
         */
        initAddressBook: function initAddressBook(callback) {
            try {
                tizen.contact.getAddressBooks(
                    function onGetAddressBook(addressbook) {
                    this.getAddressBooksSuccess(addressbook);
                    callback();
                }.bind(this),
                    this.getAddressBooksError.bind(this));
            } catch (e) {
                if (e.name === 'SecurityError') {
                    this.ui.showPopupWarning();
                }
                console.error('getAddressBooks() error: ' + e.message);
            }
        },

        /**
         * Performs counting down during waiting for contact exchange.
         * @param {number} time
         * @param {jQuery} obj
         */
        countDown: function countDown(time, obj) {
            if (!this.counterState) {
                setTimeout(function countTimer() {
                    this.countDown(time, obj);
                }.bind(this), 500);
                return;
            }

            obj.text(time);
            if (time > 0) {
                if (this.nfc.isPowered()) {
                    time -= 1;
                    this.timeOutHandler = setTimeout(
                        function countTimer() {
                        this.countDown(time, obj);
                    }.bind(this), 1000);
                } else {
                    this.nfc.timeExpired();
                }
            } else {
                this.nfc.timeExpired();
            }
        },

        /**
         * Saves contact to address book.
         */
        saveContact: function saveContact() {
            var contact = null,
                data = $('#contact').data('contactsData');
            if (!(data.phone && (data.first || data.last))) {
                this.ui.moveToStartPage('Cannot add empty contact');
                console.error('saveContact error: empty contact');
            } else {
                try {
                    contact = new tizen.Contact(data.vCard, 'VCARD_30');
                    this.addressBook.add(contact);
                    this.ui.moveToStartPage('New contact added');
                } catch (err) {
                    this.ui.moveToStartPage('Problem with new contact adding');
                    console.error('saveContact error:' + err.name);
                }
            }
        },

        /**
         * Loads contacts from address book and passes result to callback.
         *
         * @param {function} successCallback
         * @param {function} errorCallback
         */
        loadContacts: function loadContacts(successCallback, errorCallback) {
            this.addressBook.find(successCallback, errorCallback);
        }

    };

}());

app = new App();

$(document).ready(app.init.bind(app));
