/*
 * 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 $, document, console, tizen, app, TemplateManager, UiEvents,
setTimeout */
/*jslint plusplus: true*/

/**
 * @class Ui
 */
function Ui() {
    'use strict';
    this.init();
}

(function strict() {
    'use strict';
    Ui.prototype = {
        templateManager: null,

        /**
         * Is message out of range flag.
         */
        isMessageOutOfRange: false,

        /**
         * Object for Ui events.
         */
        uiEvents: null,

        /**
         * Initializes Ui object.
         */
        init: function Ui_init() {
            this.templateManager = new TemplateManager();
            this.uiEvents = new UiEvents(this);
            $(document).ready(this.domInit.bind(this));
            // Disable selection event on document;
            $.mobile.tizen.disableSelection(document);
        },

        /**
         * Performs additional initialization operations,
         * which are dependent on whether the DOM is ready.
         */
        domInit: function Ui_domInit() {
            var templates = ['main_page',
                            'chat',
                            'callerRow',
                            'contactSelect',
                            'contactRow',
                            'normalBubble'];
            this.templateManager.loadToCache(
                templates,
                this.initPages.bind(this)
            );
        },

        /**
         * Initializes application pages stored in templates.
         */
        initPages: function Ui_initPages() {
            var pages = [];

            app.model.init();

            $('#main').append(
                $(this.templateManager.get('main_page')).children()
            ).trigger('pagecreate');

            pages.push(this.templateManager.get('contactSelect'));
            pages.push(this.templateManager.get('chat'));
            $('body').append(pages.join(''));

            this.uiEvents.init();

            this.setChatCounterValue();
            this.checkChatSendButtonState();
        },

        /**
         * Scrolls chat scrollview element to the bottom.
         * @param {boolean} noCorrection
         */
        scrollToBottom: function Ui_scrollToBottom(noCorrection) {
            var talk = $('#chat-content .ui-scrollview-view'),
                heightDiff = talk.height() - talk.parent().height();
            noCorrection = noCorrection || false;
            if (heightDiff > 0) {
                setTimeout(function scrollToTalkHeight() {
                    $('#chat-content').scrollTop(talk.height());
                }, 300);
            }
            if (!noCorrection) {
                setTimeout(function scrollToBottom() {
                    app.ui.scrollToBottom(true);
                }, 200);
            }
            $('.ui-overflow-indicator-bottom').css('opacity', 0);
        },

        /**
         * Updates title of the chat page.
         * @param {string} title
         */
        setChatTitle: function Ui_setChatTitle(title) {
            $('#chat-title').text(title);
        },

        /**
         * Clears textarea content on chat page.
         */
        resetTextAreas: function Ui_resetTextAreas() {
            $('#text').val('');
            $('input[name="number"]').val('');
            $('#enterNumberCreate')
                .addClass('ui-disabled')
                .attr('tabIndex', '-1')
                .blur();
        },

        /**
         * Updates counter of the chat characters.
         * It shows available characters to the end of sms in a given encoding.
         * @param {jQuery} obj
         * @param {string} encoding
         */
        setChatCounterValue: function Ui_setChatCounterValue(obj, encoding) {
            encoding = encoding || 'gsm';
            obj = obj || $('#text');
            this.setCounterValue(obj, encoding);
        },

        /**
         * Calculates the available characters to the end of sms
         * in given encoding and updates that information to DOM obj.
         * @param {jQuery} obj
         * @param {string} encoding
         */
        setCounterValue: function Ui_setCounterValue(obj, encoding) {
            var current = app.model.getTextLength(obj.val(), encoding),
                message = app.maxMessageLength[encoding],
                numberOfMessages,
                charLeft,
                totalMax = app.totalMessageLength[encoding],
                newline = obj.val().split('\n').length - 1,
                messagesNumberHTML = '';

            if (current <= message) {
                charLeft = message - current;
                numberOfMessages = 1;
            } else {
                message -= app.multiMessageHeaderLength[encoding];
                charLeft = current % message;
                if (charLeft !== 0) {
                    charLeft = message - charLeft;
                }
                numberOfMessages = Math.ceil(current / message);
            }

            messagesNumberHTML = numberOfMessages;

            if (numberOfMessages > app.maxNumberOfMessages[encoding]) {
                messagesNumberHTML = '<span class="outOfRange">' +
                    numberOfMessages +
                    '</span>';
                this.outOfRangeMessage(true);
            } else {
                this.outOfRangeMessage(false);
            }

            obj.attr(
                'maxlength',
                totalMax - (current - obj.val().length) + newline
            )
                .parent().next().find('.counter p')
                .html(charLeft + '<span>/' + messagesNumberHTML + '</span>');
        },

        /**
         * Checks whether current message is to long or not.
         * @param {boolean} state
         */
        outOfRangeMessage: function Ui_outOfRangeMessage(state) {
            // message become out of range
            if (state && !this.isMessageOutOfRange) {
                this.rangeInfo(true);
            // message become valid
            } else if (this.isMessageOutOfRange && !state) {
                this.rangeInfo(false);
            }
            this.isMessageOutOfRange = state;
        },

        /**
         * Toggles view of info container for out of range messages.
         * @param {boolean} show
         */
        rangeInfo: function Ui_infoMessage(show) {
            var chatFooter = $('#chat-footer'),
                info = chatFooter.find('.ui-info'),
                footerHeight = 0,
                infoHeight = 30;

            if (show) {
                info.show();

                footerHeight = chatFooter.height();
                chatFooter.height(footerHeight + infoHeight);
            } else {
                info.hide();

                footerHeight = chatFooter.height();
                chatFooter.height(footerHeight - infoHeight);
            }
        },

        /**
         * Enables/disables send button state and view.
         */
        checkChatSendButtonState: function Ui_checkChatSendButtonState() {
            if (app.helpers.checkStringLength($('#text').val())) {
                $('#send')
                    .css({
                        'pointer-events': 'auto'
                    })
                    .removeClass('ui-disabled')
                    .attr('tabIndex', '0');
            } else {
                $('#send').css({'pointer-events': 'none'})
                    .addClass('ui-disabled')
                    .attr('tabIndex', '-1')
                    .blur();
            }
        },

        /**
         * Removes highlight of web-ui button.
         */
        clearSendButton: function Ui_clearSendButton() {
            $('.ui-btn-down-s').removeClass('ui-btn-down-s');
        },

        /**
         * Clears chat page elements to initial state.
         */
        resetPages: function Ui_resetPages() {
            this.resetTextAreas();
            this.setChatCounterValue();
            this.checkChatSendButtonState();
        },

        /**
         * Clears chat list on chat page.
         */
        clearChatList: function Ui_clearChatList() {
            $('#chat-title').html('');
            $('#message-chat').empty();
        },

        /**
         * Clears caller list on main page.
         */
        clearCallerList: function Ui_clearCallerList() {
            return $('#main-content .ui-listview').empty();
        },

        /**
         * Handles tap event on caller list elements.
         * @param {object} event
         * @param {jQuery} element
         */
        onCallerListElementTap: function Ui_onCallerTap(event, element) {
            event.preventDefault();
            event.stopPropagation();
            app.setCurrentNumber(element.attr('phone'));
            app.setCurrentCaller(element.attr('caller'));
            $.mobile.changePage('#chat');
        },

        /**
         * Adds contacts to contacts list on contactSelect page.
         * @param {array} sortedContactList
         */
        fillContactList: function Ui_fillContactList(sortedContactList) {
            var i, ul = $('#contactSelect-list').empty(),
                len, listElement;

            len = sortedContactList.length;

            for (i = 0; i < len; i += 1) {
                listElement = this.templateManager.get('contactRow', {
                    'number': sortedContactList[i].number,
                    'callerName': sortedContactList[i].caller
                });

                if (
                    app.helpers.validateNumberLength(
                        sortedContactList[i].number
                    )
                ) {
                    ul.append(listElement);
                }
            }

            $('li.ui-li-has-multiline', ul).on('click', function ulTap(event) {
                app.ui.onCallerListElementTap(event, $(this));
            });

            ul.trigger('create');
            ul.listview('refresh');
        },

        /**
         * Adds callers to callers list on main page.
         */
        loadCallerList: function Ui_loadCallerList() {
            var ul, i, date, caller, message;
            ul = this.clearCallerList();
            for (i in app.model.messagesList) {
                if (app.model.messagesList.hasOwnProperty(i)) {
                    caller = '';
                    message = app.model.messagesList[i];
                    date = new Date(message.lastMessage.timestamp);

                    caller = app.model.getNameByNumber(i);
                    try {
                        ul.append(
                            this.templateManager.get('callerRow', {
                                'number': i,
                                'callerName': caller,
                                'plainBody': message.lastMessage.body.plainBody
                                    .replace(/^\s+|\s+$/g, '')
                                    .replace(/\s+/g, ' ')
                                    .substring(0, 50),
                                'date': app.helpers.getDate(date),
                                'hour': date.getHours(),
                                'minutes': app.helpers
                                    .addZeroBefore(date.getMinutes())
                            })
                        );
                    } catch (err) {
                        console.log(err);
                    }
                }
            }
            ul.listview('refresh');
        },

        /**
         * Initializes chat page with inserted number.
         */
        createChatByNumber: function Ui_createChatByNumber() {
            var phoneValue = $('#number').blur()
                .val().replace(app.notNumberChars, '');
            app.setCurrentNumber(phoneValue);
            app.setCurrentCaller(app.model.getNameByNumber(phoneValue));
            setTimeout(function goToChatPage() {
                $.mobile.changePage('#chat');
            }, 100);
        },

        /**
         * Shows list of all messages on chat page.
         */
        showMessageChat: function Ui_showMessageChat() {
            var ul, li, i, date, data,
                key = app.getCurrentNumber(), messages;
            if (document.webkitVisibilityState === 'visible' &&
                    $.mobile.activePage.attr('id') === 'chat') {
                // update name if changed
                app.setCurrentCaller(app.model.getNameByNumber(key));
                $('#chat-title').text(app.getCurrentCaller());
                ul = $('#message-chat').empty();

                if (app.model.messagesList[key] !== undefined) {
                    messages = app.model.messagesList[key].messages;
                    i = messages.length;
                    while (i--) {
                        date = new Date(messages[i].timestamp);

                        data = {
                            'bubbleType': messages[i]
                                .to.length === 0 ? 'left' : 'right',
                            'label': app
                                .model.getNameByNumber(messages[i].from),
                            'caller': messages[i].caller,
                            'id': messages[i].id,
                            'plainBody': messages[i].body.plainBody,
                            'date': app.helpers.getDate(date),
                            'hour': date.getHours(),
                            'minutes': app
                                .helpers.addZeroBefore(date.getMinutes()),
                            'status': messages[i].messageStatus
                        };

                        if (!messages[i].isRead) {
                            app.model.setRead(messages[i]);
                        }

                        li = $(app.ui.templateManager
                                    .get('normalBubble', data));
                        if (messages[i].messageStatus === 'DRAFT') {
                            li.one('click', app.model.editDraft
                                    .bind(app.model, messages[i], li));
                        }
                        ul.append(li);
                    }
                    ul.listview('refresh');
                    app.ui.scrollToBottom();
                }
            }
        },

        /**
         * Updates displayed message to show or hide message status information.
         * @param {Object} message
         * @param {Number} loop
         */
        changeMessageStatus: function Ui_changeMessageStatus(message, loop) {
            var warning = $('#' + message.id + ' .warning'),
                classes,
                i,
                self = this;
            loop = loop + 1 || 0;
            if (warning.length === 1) {
                classes = warning.attr('class').split(' ');
                for (i in classes) {
                    if (classes.hasOwnProperty(i)) {
                        if (/status([A-Z]*)/.test(classes[i])) {
                            warning.removeClass(classes[i]);
                        }
                    }
                }
                warning.addClass('status' + message.messageStatus);
            } else if (loop < 3) {
                setTimeout(
                    function changeMessageStatus() {
                        self.changeMessageStatus(message, loop);
                    },
                    1000
                );
            }
        },

        /**
         * Displays chat page.
         */
        showChatPage: function Ui_showChatPage() {
            this.setChatTitle(app.getCurrentCaller());
            $.mobile.changePage('#chat');
        },

        /**
         * Displays main page.
         */
        showMainPage: function Ui_showMainPage() {
            $.mobile.changePage('#main');
        },

        /**
         * Displays alert popup with text given as parameter.
         * @param {String} text
         */
        alertPopup: function Ui_alertPopup(text) {
            setTimeout(
                function openPopup() {
                    $('#alertPopup .text').html(text);
                    $('#alertPopup').popup('open', {'positionTo': 'window'});
                },
                200
            );
        },

        /**
         * Displays error popup with text given as parameter.
         * @param {String} text
         */
        showSendErrorPopup: function Ui_showSendErrorPopup(text) {
            app.ui.alertPopup('Could not send the message.<br>' + text);
        }

    };

}());
