/*
 * 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, App, localStorage: true, TemplateManager, document */
/*global window, setTimeout, console, alert, app */

App.Ui = null;

(function strict() {
    'use strict';

    /**
     * Constructs Ui object.
     * @param {App} app
     */
    App.Ui = function App_Ui(app) {
        this.app = app;
        this.templateManager = new TemplateManager(app.config);
    };

    App.Ui.prototype = {
        /**
         * Returns the name of contact given as parameter.
         * @param {Contact} contact
         * @return {string}
         */
        prepareCallerName: function ui_prepareCallerName(contact) {
            var name = contact.name.displayName;
            return (name && name.length > 0) ? name : 'No Name';
        },

        /**
         * Shows popup with given message.
         * @param {string} message
         */
        showPopup: function ui_showPopup(message) {
            var popup = $('#alertPopup');
            if (!popup.hasClass('ui-popup')) {
                popup.popup().trigger('create');
            }
            $('.ui-popup-text', popup).text(message);
            popup.popup('open', {
                positionTo: 'window'
            });
        },

        /**
         * Closes popup.
         */
        closePopup: function ui_closePopup() {
            var activePopup = $.mobile.popup.active;
            if (activePopup) {
                if (activePopup.attr('id') === 'alertPopup') {
                    activePopup.close();
                }
            }
        },

        /**
         * Displays choose page.
         */
        createListRecord: function ui_createListRecord() {
            $.mobile.changePage('#choose');
        },

        /**
         * Returns waiting content for waiting page
         * with text given as parameter.
         * @param {string} text
         * @return {string}
         */
        getWaitingContentHtml: function getWaitingContentHtml(text) {
            var html = '';
            html += '<p class="defaultVeryBigText">';
            html += text;
            html += '</p>';

            html += '<p class="defaultCounterText" id="counter"></p>';

            return html;
        },

        /**
         * Prepares waiting page.
         * @param {string} title
         * @param {string} text
         */
        prepareWaitingPage: function ui_prepareWaitingPage(title, text) {
            var waitingBox, waitingContent,
                contentTransfer = $('#content-transfer');
            waitingBox = $('<div class="box" id="waitingBox"></div>');
            waitingContent = $(this.getWaitingContentHtml(text));
            $('#header-transfer H1').text(title);
            contentTransfer.empty();
            waitingBox.append(waitingContent);
            contentTransfer.append(waitingBox);
            $('#content-start').trigger('create');
            this.app.countDown(10, $('#counter'));
        },

        /**
         * Returns HTML string with temporaryBox DOM element.
         * @return {string}
         */
        getTemporaryBoxHtml: function ui_getTemporaryBoxHtml() {
            return '<div class="box" id="temporaryBox"></div>';
        },

        /**
         * Shows warning popup.
         */
        showPopupWarning: function ui_showPopupWarning(warning) {
            warning = warning || 'If you want to use "Contact Exchanger" you ' +
                ' must agree to access Contacts and NFC by this application.';
            $('#contact-nfc-error .ui-popup-text').text(warning);
            setTimeout(function onNfcError() {
                $('#contact-nfc-error').popup('open', {
                    'positionTo': 'window'
                });
            }, 500);
        },

        /**
         * Returns HTML string with content for temporaryBox DOM element.
         * @return {string}
         */
        getTemporaryBoxContentHtml: function ui_getTemporaryBoxContentHtml() {
            return '<p class="defaultText">' +
                'Default card is not defined yet!<br/>' +
                'Do you want to define it now?' + '</p>';
        },

        /**
         * Displays temporary content on start page.
         */
        loadTemporaryContent: function ui_loadTemporaryContent() {
            var temporaryBox, temporaryContent, temporaryButton;

            temporaryBox = $(this.getTemporaryBoxHtml());
            temporaryContent = $(this.getTemporaryBoxContentHtml());
            temporaryButton = $(this.getButtonHtml('Create default card'));

            temporaryButton.on('click', function onClick(event) {
                event.preventDefault();
                $.mobile.changePage('#choose');
            });

            temporaryBox.append(temporaryContent).append(temporaryButton);

            $('#content-start').empty().append(temporaryBox).trigger('create');
        },

        /**
         * Returns HTML string with button element containing text
         * given as parameter.
         * @param {string} text Button text.
         * @return {string}
         */
        getButtonHtml: function ui_getButtonHtml(text) {
            return '<div data-role="button" class="ui-btn-create">' +
                text + '</div>';
        },

        /**
         * Returns comment HTML string for default contact with data
         * obtained from data object given as parameter.
         * @param {object} data
         * @return {string}
         */
        getCommentHtml: function ui_getCommentHtml(data) {
            var def_name = $('<p class="comment" id="comment-name">')
                .text(data.caller).html();
            return '<div id="comment">' +
                '<p class="comment">Your default contact</p>' +
                '<p class="comment" id="comment-userName">' +
                def_name + '</p>' + '<p class="comment" id="comment-phone">' +
                data.phoneNumber + '</p>' + '</div>';
        },


        /**
         * Performs action after click event on contact button.
         * @param {event} event
         */
        changeContact: function ui_changeContact(event) {
            event.preventDefault();
            $.mobile.changePage('#choose');
        },

        /**
         * Returns change contact button.
         * @return {jQuery}
         */
        getChangeContactButton: function ui_getChangeContactButton() {
            var changeContactButton;
            changeContactButton =
                $(this.getButtonHtml('Change your default contact'));
            changeContactButton.on('click', this.changeContact);
            return changeContactButton;
        },

        /**
         * Performs action after click event on read from card button.
         * @param {event} event
         */
        readFromCard: function ui_readFromCard(event) {
            event.preventDefault();
            if (this.app.nfc.isNfcPowered()) {
                try {
                    $('#transfer').data('option', 'read');
                    $.mobile.changePage('#transfer');
                } catch (err) {
                    console.error('ui_readFromCard: ', err.message);
                }
            } else {
                $.mobile.changePage('#start');
                alert('Please turn on NFC adapter');
            }
        },

        /**
         * Creates and returns read from card button.
         * @return {jQuery}
         */
        getReadFromCardButton: function ui_getReadFromCardButton() {
            var readFromCardButton;
            readFromCardButton = $(this.getButtonHtml('Read from card'));
            readFromCardButton.on('click', this.readFromCard.bind(this));
            return readFromCardButton;
        },

        /**
         * Performs action after click event on write to card button.
         * @param {event} event
         */
        writeToCard: function ui_writeToCard(event) {
            event.preventDefault();
            if (this.app.nfc.isNfcPowered()) {
                try {
                    $('#transfer').data('option', 'write');
                    $.mobile.changePage('#transfer');
                } catch (err) {
                    console.error('ui_writeToCard: ', err.message);
                }
            } else {
                alert('Please turn on NFC adapter');
            }
        },

        /**
         * Creates and returns 'Write to card' button.
         * @return {jQuery}
         */
        getWriteToCardButton: function ui_getWriteToCardButton() {
            var writeToCardButton;
            writeToCardButton = $(this.getButtonHtml('Write to card'));
            writeToCardButton.on('click', this.writeToCard.bind(this));
            return writeToCardButton;
        },

        /**
         * Performs action after click event on 'Communicate
         * with another device' button.
         * @param {event} event
         */
        commWithOtherDevice: function ui_commWithOtherDevice(event) {
            event.preventDefault();
            if (this.app.nfc.isNfcPowered()) {
                try {
                    $('#transfer').data('option', 'communicate');
                    $.mobile.changePage('#transfer');
                } catch (err) {
                    console.error('ui_commWithOtherDevice: ', err.message);
                }
            } else {
                alert('Please turn on NFC adapter');
            }
        },

        /**
         * Creates and returns 'Communicate with another device' button.
         * @return {jQuery}
         */
        getCommWithOtherDeviceBtnn: function ui_getCommWithOtherDeviceBtnn() {
            var communicateWithOtherDeviceButton;
            communicateWithOtherDeviceButton =
                $(this.getButtonHtml('Communicate with another device'));
            communicateWithOtherDeviceButton
                .on('click', this.commWithOtherDevice.bind(this));
            return communicateWithOtherDeviceButton;
        },

        /**
         * Displays start content on start page.
         */
        loadStartContent: function ui_loadStartContent() {
            var startBox, contentStart, gap, comment;
            contentStart = $('#content-start');
            startBox = $('<div class="box" id="startBox"></div>');
            gap = $('<div class="gap"></div>');
            comment = $(this.getCommentHtml(localStorage));

            contentStart.empty();
            startBox
                .append(this.getChangeContactButton())
                .append(gap.clone())
                .append(this.getReadFromCardButton())
                .append(gap.clone())
                .append(this.getWriteToCardButton())
                .append(gap.clone())
                .append(this.getCommWithOtherDeviceBtnn())
                .prepend(comment);

            contentStart.append(startBox);
            contentStart.trigger('create');
        },

        /**
         * Displays start page.
         */
        loadStartPage: function ui_loadStartPage() {
            if (localStorage.started === undefined) {
                this.loadTemporaryContent();
            } else {
                this.loadStartContent();
            }
        },

        /**
         * Creates and returns li HTML string element with contact data
         * displayed on contact page.
         * @param {string} value
         * @param {string} label
         * @return {string}
         */
        getLiHtml: function ui_getLiHtml(value, label) {
            var html;
            html = '<li class="ui-li-multiline" id="' + label + '">' +
                '<a href="#">' + '<span>' + label + '</span>' +
                '<span class="ui-li-text-sub">' + ((!value) ? '...' : value) +
                '</span>' + '</a>' + '</li>';
            return html;
        },

        /**
         * Creates and returns HTML ul string element with contact data
         * displayed on contact page.
         * @param {object} contactInfo
         * @param {string} contactInfo.phone
         * @param {string} contactInfo.phone_type
         * @param {string} contactInfo.first
         * @param {string} contactInfo.middle
         * @param {string} contactInfo.last
         * @param {string} contactInfo.vCard
         * @return {string}
         */
        getContactsUlHtml: function ui_getContactsUlHtml(contactInfo) {
            var html;
            html = '<ul data-role="listview" id="contacts-data">';
            html += this.getLiHtml(contactInfo.first, 'First Name');
            html += this.getLiHtml(contactInfo.middle, 'Middle Name');
            html += this.getLiHtml(contactInfo.last, 'Last Name');
            html += this.getLiHtml(contactInfo.phone, 'Phone');
            html += this.getLiHtml(contactInfo.phone_type, 'Type');
            html += this.getLiHtml(contactInfo.vCard, 'vCard');
            html += '</ul>';
            return html;
        },

        /**
         * Creates and returns HTML li string element with contact data
         * displayed on choose page.
         * @param {Contact} contact
         * @return {string}
         */
        getContactsListElement: function ui_getContactsListElement(contact) {
            var caller = $('<span class="ui-li-text-sub">')
                    .text(contact.caller).html(),
                phoneNumber = contact.phoneNumber,
                html = '<li class="ui-li-multiline">' +
                    '<a href="#">' + caller + '<span class="ui-li-text-sub">' +
                    phoneNumber + '</span>' + '</a>' + '</li>';
            return html;
        },

        /**
         * Displays contact data on contact page.
         * @param {object} contact
         * @param {string} contact.phone
         * @param {string} contact.phone_type
         * @param {string} contact.first
         * @param {string} contact.middle
         * @param {string} contact.last
         * @param {string} contact.vCard
         */
        prepareContactsTemplate: function ui_prepareContactsTemplate(contact) {
            $('#content-contact > .ui-scrollview-view')
                .empty()
                .append(this.getContactsUlHtml(contact));
            $('#content-contact').trigger('create');
        },

        /**
         * Compares contacts by caller in order to support sorting process.
         * @param {Contact} a
         * @param {Contact} b
         * @return {number}
         */
        contactsCompare: function ui_contactsCompare(a, b) {
            if (a.caller < b.caller) {
                return -1;
            }
            if (a.caller > b.caller) {
                return 1;
            }
            return 0;
        },

        /**
         * Creates and returns array of objects with contacts data
         * displayed on choose page.
         * @param {Contact[]} contacts
         * @return {array}
         */
        createSortedContactArray:
            function ui_createSortedContactArray(contacts) {
                var i = 0, len = contacts.length, sortedContactList = [],
                    contact = null, phoneNumber = null;

                for (i = 0; i < len; i += 1) {
                    contact = contacts[i];
                    if (contact.phoneNumbers.length === 0) {
                        phoneNumber = '';
                    } else {
                        phoneNumber = contact.phoneNumbers[0].number;
                    }
                    sortedContactList.push({
                        caller: this.prepareCallerName(contact),
                        firstName: contact.name.firstName || '',
                        middleName: contact.name.middleName || '',
                        lastName: contact.name.lastName || '',
                        phoneNumber: phoneNumber,
                        id: contact.id,
                        vCard: contact.convertToString('VCARD_30'),
                        contact: contact
                    });
                }
                sortedContactList.sort(this.contactsCompare);

                return sortedContactList;
            },

        /**
         * Creates and returns jQuery ul object with contacts data
         * displayed on choose page.
         * @param {Contact[]} contacts
         * @return {jQuery}
         */
        createSortedContactList: function ui_createSortedContactList(contacts) {
            var sortedContactList = this.createSortedContactArray(contacts),
                ul = $('<ul data-role="listview" id="list-choose"></ul>'),
                i = 0,
                len = sortedContactList.length,
                listElement = null,
                self = this,
                contact = null,
                listElementTap = function onListElementTap(event) {
                    event.preventDefault();
                    $(this).addClass('selected').siblings()
                        .removeClass('selected');
                    self.app.saveDefaultCard();
                };

            for (i = 0; i < len; i += 1) {
                contact = sortedContactList[i];
                if (contact.phoneNumber !== '') {
                    listElement = $(this.getContactsListElement(contact));
                    listElement
                        .data('caller', contact.caller)
                        .data('firstName', contact.firstName)
                        .data('middleName', contact.middleName)
                        .data('lastName', contact.lastName)
                        .data('phoneNumber', contact.phoneNumber)
                        .data('id', contact.id)
                        .data('vCard', contact.vCard);
                    if (localStorage.id === listElement.data('id')) {
                        listElement.addClass('selected');
                    }
                    ul.append(listElement);
                }
            }
            ul.on('tap taphold click', 'li', listElementTap);
            return ul;
        },

        /**
         * Shows contacts list on choose page.
         * @param {Contact[]} contacts
         */
        showContactsList: function ui_showContactsList(contacts) {
            var view = $('#content-choose > .ui-scrollview-view').empty(),
                page = $('#choose');

            if (contacts.length === 0) {
                page.addClass('ui-empty-state');
                view.append(
                    '<h2>No contacts</h2>' +
                    'Contact list should contain at least one item.'
                );
            } else {
                page.removeClass('ui-empty-state');
                view.append(this.createSortedContactList(contacts));
            }
            $('#content-choose').trigger('create');
        },

        /**
         * Changes the page to the start page.
         * @param {string} monit
         */
        moveToStartPage: function ui_moveToStartPage(monit) {
            $('#start').data('monit', monit || '');
            $.mobile.changePage('#start');
        },

        /**
         * Returns true when the current page is active page, false otherwise.
         * @param {number} id
         * @return {boolean}
         */
        isActivePage: function ui_isActivePage(id) {
            return (id === $.mobile.activePage.attr('id'));
        },

        /**
         * Performs refresh action for active page.
         * @param {number} id
         */
        refreshIfActivePage: function ui_refreshIfActivePage(id) {
            if (this.isActivePage(id)) {
                $.mobile.activePage
                    .trigger('pagebeforeshow')
                    .trigger('pageshow');
            }
        },

        /**
         * Changes the page to the contact page.
         * @param {object} obj
         */
        moveToContactPage: function ui_moveToContactPage(obj) {
            $('#start').data('monit', '');
            $('#contact').data('contactsData', obj);
            $.mobile.changePage('#contact');
        },

        /**
         * Binds events to pages.
         */
        defineEvents: function ui_defineEvents() {
            var self = this;

            $('#header-start')
                .on('click', '.ui-btn-back.ui-focus', function onClick() {
                    return false;
                });

            $('#footer-contact').on('click', '.ui-btn-back',
                function onClick(event) {
                    event.preventDefault();
                    $.mobile.changePage('#start');
                });

            $('#footer-choose').on('click', '.ui-btn-back',
                function onClick(event) {
                    event.preventDefault();
                    $.mobile.changePage('#start');
                });

            $('#choose').on('pageshow', function onChoosePageShow() {
                self.app.loadContacts(
                    self.showContactsList.bind(self),
                    function onContactsLoadError(e) {
                        alert('Cannot load the contacts list: ' + e.message);
                        console.error(e.message, e);
                    }
                );
            });

            $('#contact').on('pageshow', function onContactPageShow() {
                self.prepareContactsTemplate($(this).data('contactsData'));
            });

            $('#save-contact').on('click', function onSaveContactClick(event) {
                event.preventDefault();
                self.app.saveContact();
            });

            $('#start').on('pagebeforeshow', function onStartPageBeforeShow() {
                if (self.app.started) {
                    self.loadStartPage();
                }
            });

            $('#start').on('pageshow', function onStartPageShow() {
                var obj = $(this),
                    monit = obj.data('monit');
                if (monit !== '' && monit !== undefined) {
                    self.showPopup(obj.data('monit'));
                    obj.data('monit', '');
                }
            });

            $('#contact-nfc-error').bind({
                popupafterclose: function onPopupAfterClose() {
                    try {
                        tizen.application.getCurrentApplication().exit();
                    } catch (err) {
                        console.error('getCurrentApplication: ', err.message);
                    }
                }
            });

            window.addEventListener('tizenhwkey', function onTizenHwKey(e) {
                if (e.keyName === 'back') {
                    if ($.mobile.popup.active) {
                        $.mobile.popup.active.close();
                    } else if ($.mobile.activePage.attr('id') === 'start') {
                        try {
                            tizen.application.getCurrentApplication().exit();
                        } catch (err) {
                            console.error(
                                'getCurrentApplication: ', err.message
                            );
                        }
                    } else {
                        self.app.nfc.timeExpired();
                    }
                }
            });

            document.addEventListener('webkitvisibilitychange',
                function onVisibilityChange() {
                    if (document.webkitVisibilityState === 'visible') {
                        if ($.mobile.activePage.attr('id') === 'choose') {
                            $.mobile.activePage.trigger('pageshow');
                        }
                        app.counterState = true;
                    } else {
                        app.counterState = false;
                    }
                });

            $('#transfer').on('pageshow',
                function onTransferPageShow() {
                    if (self.app.nfc.isNfcPowered()) {
                        try {
                            var option = $(this).data('option');
                            if (option === 'read') {
                                self.prepareWaitingPage(
                                    'Card to device',
                                    'PUT WIRELESS TAG<br>CLOSE TO<br>' +
                                        'YOUR DEVICE'
                                );
                                self.app.nfc.card.setTagDetectRead();
                            } else if (option === 'write') {
                                self.prepareWaitingPage(
                                    'Device to card',
                                    'PUT WIRELESS TAG<br>CLOSE TO<br>' +
                                        'YOUR DEVICE'
                                );
                                self.app.nfc.card.setTagDetectWrite();
                            } else {
                                self.prepareWaitingPage('Device to device',
                                    'PUT YOUR DEVICE<br>CLOSE TO<br>' +
                                        'OTHER DEVICE');
                                self.app.nfc.peer.setTargetDetect();
                            }
                        } catch (err) {
                            console.error(err.message);
                        }
                    } else {
                        $.mobile.changePage('#start');
                        alert('Please turn on NFC adapter');
                    }
                });
        }

    };

}());
