
var $upArrowTemplate = $('<div style="width: 0;height: 0;border-style: solid;border-width: 0 10px 20px 10px;border-color: transparent transparent #ffffff transparent;line-height: 0px;_border-color: #000000 #000000 #000000 #ffffff; position:absolute;"></div>');

var $rightArrowTemplate = $('<div style="width: 0;height: 0;border-style: solid;border-width: 10px 0 10px 20px;border-color: transparent transparent transparent #ffffff;line-height: 0px;_border-color: #000000 #000000 #000000 #ffffff; position:absolute;"></div>');

GLOBAL_taskFormHubOverlay = new function () {
    var self = this;
    var $taskFormHub_overlay = $('.taskFormHub-overlay');
    if (!$taskFormHub_overlay.length) {
        $taskFormHub_overlay = $('<div class="taskFormHub-overlay userData2Overlay hidden">');
        $taskFormHub_overlay.css({ 'position': 'fixed', 'width': '100%', 'height': '100%', 'top': '0px', 'left': '0px', 'background-color': '#000000', 'opacity': '1' });
        $('body').append($taskFormHub_overlay);
    }

    $taskFormHub_overlay.click(function () {
        self.close();
    });

    this.open = function (data, options) {
        var _options = {};
        $.extend({}, _options, options || {});
        
        $taskFormHub_overlay.html(data);
        $taskFormHub_overlay.show();

        return this;
    }

    this.close = function () {
        if ($taskFormHub_overlay.length) {
            $taskFormHub_overlay.hide();
        }
    }
}

GLOBAL_taskFormHubDialog = new function () {
    var self = this;
    var $dialog = $('<div class="taskFormHub-overlaydialog"></div>');;
    $dialog.dialog({ autoOpen: false });

    this.openDialog = function (data, options) {
        this.closeDialog();
        $dialog.html(data);
        $dialog.dialog($.extend({}, {
            autoOpen: false,
            modal: true,
            width: 'auto',
            //position: ['center',20],
            buttons: {
                Ok: function () {
                    self.closeDialog();
                }
            },
            open: function () {
                
            }
        }, options));
        $dialog.dialog('open');
        $dialog.find('.autogrow').elastic();
        $dialog.dialog('option', 'position', 'center');
        return $dialog;
    }

    this.closeDialog = function () {
        $dialog.empty();
        $dialog.dialog("close");
    }

    this.getContent = function () {
        return $dialog.children();
    }
}

$(document).ready(function () {
    //Объект для проверки что хаб не подключен
    var _hubNotStartedObject = {};

    var taskFormHubObserver = new function () {
        var thatObserver = this;
        var taskFormHub;
        var hubStarted = false;

        this.isHubStarted = function () {
            return hubStarted;
        }
        this.getTaskFormHub = function () {
            return taskFormHub;
        }

        var $taskform = $('#taskform');
        var $taskFromBottom = $('.formbottom')
        var $taskFormHub_viewCount = $('#taskFormHub_viewCount');
        var $taskFormHub_viewUsers = $('#taskFormHub_viewUsers');

        //не актуально, есть баг когда п2 блокирует(сохраняет) заявку у п1, в это же время у п1 происходит потеря подключения и п1 больше никогда не узнает что п2 разблокировал заявку(после успешного сохранения)
        var taskFormLockedByUser = undefined;
        var taskFormSubmitedByUser = undefined;

        this.getBlocks = function () {
            return _blocks;
        }
        var _blocks = {};
        this.addBlock = function(group, name, options) {
            var opts = $.extend({}, { group: group, name: name, selector: '[name="' + name + '"]' }, options);
            var item = new ItemData(thatObserver, opts);
            if (item.IsOnForm()) {
                _blocks[name] = item;
            }
        }

        this.addCustomBlock = function (itemData) {
            if (itemData.IsOnForm()) {
                _blocks[itemData._options.name] = itemData;
            }
        }

        //////////////////////////////////////////////////////
        //custom
        this.addCustomBlock(new NameItemData(thatObserver));
        this.addBlock('main', 'description');
        this.addCustomBlock(new DeadlineItemData(thatObserver));
        this.addCustomBlock(new StatusItemData(thatObserver));
        this.addCustomBlock(new PriorityItemData(thatObserver));
        this.addCustomBlock(new ExpenseItemData(thatObserver));
        this.addCustomBlock(new ParticipantsItemData(thatObserver));
        this.addCustomBlock(new ExecutorsItemData(thatObserver));
        this.addCustomBlock(new ExecutorGroupItemData(thatObserver));
        this.addCustomBlock(new CommentItemData(thatObserver));
        this.addCustomBlock(new CreatorItemData(thatObserver));
        this.addCustomBlock(new CategoryItemData(thatObserver));
        this.addCustomBlock(new AssetItemData(thatObserver));
        this.addCustomBlock(new MainFilesItemData(thatObserver));
        //system fields
        this.addCustomBlock(new ClosedItemData(thatObserver));
        this.addCustomBlock(new ReactionDateItemData(thatObserver));
        this.addCustomBlock(new ReactionDateFactItemData(thatObserver));
        this.addCustomBlock(new ResolutionDateFactItemData(thatObserver));
        this.addCustomBlock(new EvulationItemData(thatObserver));
        this.addCustomBlock(new MassIncidentsItemData(thatObserver));
        ////////////////////////////////////////////////////
        //доп. поля (TODO проблема с рекурсивными группами)
        $.each($('[id^="field"]'), function (k, v) {
            var $v = $(v);
            var name = $v.attr('name');
            var id = $v.attr('id');
            if ($v.is('input[type="file"]')) {
                thatObserver.addCustomBlock(new FieldFileItemData(thatObserver, id));
            }
            else if ($v.parent().is('[comboboxholder]')) {
                thatObserver.addCustomBlock(new FieldSelectItemData(thatObserver, id));
            }
            else if ($v.is('input[type="checkbox"]')) {
                thatObserver.addCustomBlock(new FieldCheckboxItemData(thatObserver, id));
            }
            else {
                thatObserver.addCustomBlock(new FieldItemData(thatObserver, { group: 'field', name: name, selector: '#' + id }));
            }
        });
        //////////////////////////////////////////////////////

        function updateAllBlockStateByUser(userConnectionId, userId, userName, blocksData) {
            $.each(blocksData, function (k, v) {
                var b = _blocks[v.name];
                if (b) {
                    b.Append1(userConnectionId, userId, userName, v.data);
                }
            });
        }

        function userDisconnected(userData) {
            if (userData) {
                $.each(getBlocksName(), function (k, v) {
                    _blocks[v].Reset1(userData.userConnectionId, userData.userId, userData.userName);
                });
            }
        }

        function getBlocksName() {
            var result = [];
            for (var key in _blocks) {
                if (_blocks.hasOwnProperty(key)) {
                    result.push(key);
                }
            }
            return result;
        }

        function getBlocksNameChanged() {
            var result = [];
            for (var key in _blocks) {
                if (_blocks.hasOwnProperty(key) && _blocks[key].IsChanged()) {
                    result.push(key);
                }
            }
            return result;
        }

        this.init = function () {
            $.connection.hub.qs = { 'taskId': $('#id').val() };
            $.connection.hub.logging = true;

            taskFormHub = $.connection.taskFormHub;

            clientFunctions();

            $.connection.hub.error(function (error) {
                console.log('SignalR error: ' + error)
            });

            //Открываем соединение
            $.connection.hub.start().done(function () {
                serverFunctions();
            });
            var timeout = 1; //sec
            var reconnectCount = 0;
            var tmpl_hub_connection = tmpl('<span>' + TaskFormHubResources.Connection_Connect + '</span>');
            var tmpl_hub_reconnecting = tmpl('<span>' + TaskFormHubResources.Connection_Reconnect + '</span>');
            var tmpl_hub_disconnected = tmpl('<span>' + TaskFormHubResources.Connection_Disconect + '</span>');
            $.connection.hub.stateChanged(function (state) {

                function showConnectionLostMessage(show, text) {
                    var $formbottom_connectionLost = $taskFromBottom.find('.taskformhub-connectionlost');
                    if (show) {
                        hubStarted = false;
                        if (!$formbottom_connectionLost.length) {
                            $('.formbottom').prepend('<div class="taskformhub-connectionlost details" style="color:#737373"></div>');
                            $formbottom_connectionLost = $taskFromBottom.find('.taskformhub-connectionlost');
                        }
                        $formbottom_connectionLost.html(text);
                        $('.save,.saveandreturn,.save-ext').attr('disabled', true);
                    }
                    else {
                        hubStarted = true;
                        var $taskFormConnectionId = $('input[name="taskFormConnectionId"]');
                        if (!$taskFormConnectionId.length) {
                            $taskform.append('<input type="hidden" name="taskFormConnectionId">');
                            $taskFormConnectionId = $('input[name="taskFormConnectionId"]');
                        }
                        $taskFormConnectionId.val($.connection.hub.id);

                        $formbottom_connectionLost.remove();
                        $('.save,.saveandreturn,.save-ext').attr('disabled', false);
                    }
                }

                switch (state.newState) {
                    case $.signalR.connectionState.connecting:
                        {
                            reconnectCount++;
                            $taskFormHub_viewCount.text(0);
                            var text = tmpl_hub_connection({ reconnectCount: reconnectCount });
                            $taskFormHub_viewUsers.html(text).css('color', '#737373');
                            showConnectionLostMessage(true, text);
                        }
                        break;
                    case $.signalR.connectionState.connected:
                        {
                            reconnectCount = 0;
                            timeout = 1;
                            showConnectionLostMessage(false);
                        }
                        break;
                    case $.signalR.connectionState.reconnecting:
                        {
                            $taskFormHub_viewCount.text(0);
                            var text = tmpl_hub_reconnecting({ reconnectCount: reconnectCount });
                            $taskFormHub_viewUsers.html(text).css('color', '#737373');
                            showConnectionLostMessage(true, text);
                        }
                        break;
                    case $.signalR.connectionState.disconnected:
                        {
                            timeout++;
                            if (timeout > 15) timeout = 15;
                            $taskFormHub_viewCount.text(0);
                            var text = tmpl_hub_disconnected({ reconnectCount: reconnectCount, timeout: timeout });
                            $taskFormHub_viewUsers.html(text).css('color', '#737373');
                            showConnectionLostMessage(true, text);
                            //reconnecting after {timeout} sec
                            setTimeout(function () {
                                $.connection.hub.start();
                            }, timeout * 1000);

                            //очистить инфу у всех блоков
                            $.each(getBlocksName(), function (k, v) {
                                _blocks[v].ResetAll();
                            });
                        }
                        break;
                }
            });

            return this;
        }

        this.onVersionChangedData = function (userId, userName, date, newVersion, submitedData) {
            //если перевели в согласование то перегрузим страницу или был поменян сервис или тип
            //TODO сохранение измененных блоков в localStorage чтобы после перегрузки восстановить

            var isConcurrence = submitedData && submitedData.hasOwnProperty('statusid') && submitedData['statusid'].IsConcurrence;
            var isServiceOrType = submitedData && (submitedData.hasOwnProperty('typeid') || submitedData.hasOwnProperty('serviceid'));

            if (isConcurrence || isServiceOrType) {

                var alertMessage = isConcurrence
                    ? window.TaskFormHubResources.TaskStatusChangeIsConcurrence + ' "' + submitedData['statusid'].Name + '"<br><br>' + window.TaskFormHubResources.RefreshPage
                    : window.TaskFormHubResources.TaskServiceTypeChange + '<br><br>' + window.TaskFormHubResources.RefreshPage;

                customValidateEx.push(function() {
                    alert(alertMessage);
                    return false;
                });

                var dialogMessage = isConcurrence
                    ? '<div><b>' + window.TaskFormHubResources.TaskStatusChangeIsConcurrence + ' "' + submitedData['statusid'].Name + '"<br><br>' + window.TaskFormHubResources.RefreshPageAndOk + '</b></div>'
                    : '<div><b>' + window.TaskFormHubResources.TaskServiceTypeChange + '<br><br>' + window.TaskFormHubResources.RefreshPageAndOk + '</b></div>';

                GLOBAL_taskFormHubDialog.openDialog(dialogMessage ,
                    {
                        maxWidth: '900',
                        title: window.TaskFormHubResources.TaskChanged,
                        buttons: {
                            Ok: function() {
                                window.location.reload(true);
                            }
                        },
                        beforeClose: function (e, ui) {
                            $('.save,.saveandreturn,.save-ext').attr('disabled', true);
                            $('.saveicon,.saveandreturnicon,.save-ext').attr('disabled', true);
                        }
                    });
                return;
            }

            taskFormLockedByUser = undefined;
            $('#changed').val(date);
            if (parseInt($('#version').val()) == newVersion) {
                GLOBAL_taskFormHubDialog.closeDialog();
                return;
            }
            $('#version').val(newVersion);
            var blocksConflict = thatObserver.conflictManager.init(userId, userName, date, submitedData);

            var blocksTitle = [];
            var blocksTitleConflict = [];
            var conflictBlockFirst;
            for (var blockName in submitedData) {
                var block = _blocks[blockName];
                if (!submitedData.hasOwnProperty(blockName) || !block || !block.IsOnForm() || block.TaskRightsDisplayType() == ItemDataHelper.TaskRightsDisplayType.None) {
                    continue;
                }

                if (blocksConflict.indexOf(blockName) != -1) {
                    if (!conflictBlockFirst) {
                        conflictBlockFirst = block;
                    }
                    blocksTitleConflict.push(block.GetBlockTitle());
                }
                else {
                    blocksTitle.push(block.GetBlockTitle());
                }
            }
            getWorkflowStatuses();

            var $divData = $('<div/>');

            if (userId) {
                $divData.append('<div><b>(' + date + ') ' + userName + ' ' + TaskFormHubResources.UserChangeTask + '</b></div>');
            }
            else {
                $divData.append('<div><b>(' + date + ')  ' + TaskFormHubResources.SystemChangeTask + '</b></div>');
            }

            $divData.append('<div class="spacer10"/>');

            if (blocksTitleConflict.length > 0) {
                var $conflictsDiv = $('<div></div>');
                var $conflictsTable = $('<table></table>');
                var blocksTitleConflictLength = blocksTitleConflict.length;
                if (blocksTitleConflictLength > 5) {
                    blocksTitleConflictLength = 5;
                }
                var blocksTitleConflict2 = blocksTitleConflict.slice(0, blocksTitleConflictLength);
                for (var i = 0; i < blocksTitleConflictLength; i++) {
                    $conflictsTable.append('<tr><td style="padding-left:10px;">' + blocksTitleConflict2[i] + '</td></tr>');
                }
                var rowspan = blocksTitleConflictLength;
                if (blocksTitleConflict.length > 5) {
                    $conflictsTable.append('<tr><td style="padding-left:10px;"><b>...</b></td></tr>');
                    rowspan++;
                }
                $conflictsTable.find('tr:first').prepend('<td rowspan="' + rowspan + '"><i class="fa fa-exclamation-circle" style="color:red"></i> ' + TaskFormHubResources.WithConflicts + '</td>');
                $conflictsDiv.append($conflictsTable);
                $divData.append($conflictsDiv);
                $divData.append('<div class="spacer10"/>');

                GLOBAL_taskFormHubDialog.openDialog($divData, {
                    maxWidth: '900',
                    title: TaskFormHubResources.TaskChanged,
                    buttons: {
                        Ok: function () {
                            $(this).dialog("close");
                            if (conflictBlockFirst) {
                                conflictBlockFirst.ConflictNotResolvedScroll();
                            }
                        }
                    }
                });
            }
            else if (blocksTitle.length > 0) {
                try {
                    var $rightNotify = $('.taskFromHub-rightNotify');
                    if ($rightNotify.data('timeouthandle')) {
                        clearTimeout($rightNotify.data('timeouthandle'));
                    }
                    if ($rightNotify.length > 0) {
                        $rightNotify.remove();
                    }
                    $rightNotify = $('<div class="taskFromHub-rightNotify" style="position: fixed; bottom: 20px; right: 20px; width: auto; color: #fff; z-index: 1; background: #3dc763; padding:10px; border-radius:5px;"><i class="fa fa-exclamation-circle" style="color:green"></i> ' + TaskFormHubResources.TaskChanged + '</div>');
                    $('body').append($rightNotify);
                    $rightNotify.data('timeouthandle', setTimeout(function () {
                        if ($rightNotify.data('timeouthandle')) {
                            $('.taskFromHub-rightNotify').fadeOut();
                        }
                    }, 5000));
                }
                catch (e) { }
            }

            var $formbottomlockforminfo = $('#formbottomlockforminfo');
            if ($formbottomlockforminfo.length) {
                $formbottomlockforminfo.remove();
            }

            return blocksConflict;
        }

        function clientFunctions() {
            taskFormHub.client.onFormInfo = function (/*viewCount,*/ groupResult, disconnectedUserData) {
                var groupResultLength = groupResult.length;
                for (var i = 0; i < groupResultLength; i++) {
                    if (groupResult[i].connectionId == $.connection.hub.id) {
                        var myData = groupResult[i];
                        groupResult.splice(i, 1);
                        myData.userName = TaskFormHubResources.You;
                        groupResult.splice(0, 0, myData);
                        break;
                    }
                }
                
                var uniqueGroupResult = [];
                for (var i = 0; i < groupResultLength; i++) {
                    var item = groupResult[i];
                    if($.grep(uniqueGroupResult, function (v) { return v.userId == item.userId }).length > 0)
                        continue;
                    uniqueGroupResult.push(item);
                }

                groupResultLength = uniqueGroupResult.length;
                var maxLength = 5;
                if (groupResultLength > maxLength) {
                    groupResultLength = maxLength;
                }
                var groupResult2 = uniqueGroupResult.slice(0, groupResultLength);
                //$taskFormHub_viewUsers.html(tmpl_formInfo_viewUsers(groupResult)).css('color','#2583cb');
                $taskFormHub_viewUsers
                    .empty()
                    .css('color', '#2583cb');
                for (var i = 0; i < groupResultLength; i++) {
                    var data = groupResult2[i];
                    //var $span = $('<span data-userid="'+data.userId+'" data-connectionid="'+data.connectionId+'" style="margin:2px;">'+data.userName+'</span>');
                    var $span = $('<span data-userid="' + data.userId + '" style="margin:2px;">' + data.userName + '</span>');
                    if (groupResult2[i + 1]) {
                        $span.append(', ');
                    }
                    $taskFormHub_viewUsers.append($span);
                }
                if (uniqueGroupResult.length > maxLength) {
                    $taskFormHub_viewUsers.append('<b> ...</b>');
                }

                $taskFormHub_viewUsers.closest('table').attr('title', uniqueGroupResult.map(function (v) { return v.userName;}).join(', '));

                $taskFormHub_viewCount.text(uniqueGroupResult.length);

                if (disconnectedUserData) {
                    userDisconnected(disconnectedUserData);
                }

            };

            taskFormHub.client.onBlockChanged = function (action, userConnectionId, blockName, userId, userName, data) {
                if (!_blocks[blockName])
                    return;

                if (action == 'changed') {
                    _blocks[blockName].Append1(userConnectionId, userId, userName, data);
                }
                else if (action == "nochanged") {
                    _blocks[blockName].Reset1(userConnectionId, userId, userName, data);
                }
            };

            taskFormHub.client.onSendSelfBlocksToGroup = function () {
                var result = [];
                for (var key in _blocks) {
                    if (_blocks.hasOwnProperty(key) && _blocks[key].IsChanged()) {
                        result.push({ name: key, data: _blocks[key].GetSendBlockChangeData() });
                    }
                }
                if (result.length) {
                    thatObserver.ToServerInvoke('SendSelfBlocksStateToGroup', result);
                }
            }

            taskFormHub.client.onSendSelfBlocksToUser = function (userConnectionId) {
                var result = [];
                for (var key in _blocks) {
                    if (_blocks.hasOwnProperty(key) && _blocks[key].IsChanged()) {
                        result.push({ name: key, data: _blocks[key].GetSendBlockChangeData() });
                    }
                }
                if (result.length) {
                    thatObserver.ToServerInvoke('SendSelfBlocksStateToUser', userConnectionId, result);
                }
            }

            taskFormHub.client.updateAllBlockStateByUser = function (userConnectionId, userId, userName, blocksData) {
                updateAllBlockStateByUser(userConnectionId, userId, userName, blocksData);
            }

            taskFormHub.client.lockForm = function (userId, userName, date) {
                taskFormLockedByUser = { userId: userId, userName: userName };
                var $divData = $('<div id="formbottomlockforminfo" style="color:#737373;">' + userName + ' ' + date + ' ' + TaskFormHubResources.UserStartSavingForm + '</div>');
                //GLOBAL_taskFormHubDialog.openDialog($divData);
                $('.formbottom').prepend($divData);
                //через 3 секунды включить кнокпи
                $('.save,.saveandreturn,.save-ext').attr('disabled', true);
                setTimeout(function () {
                    $('.save,.saveandreturn,.save-ext').attr('disabled', false);
                    $divData.remove();
                }, 3000);
            }

            taskFormHub.client.unlockForm = function (userId, userName, date) {
                taskFormLockedByUser = undefined;
                $('.save,.saveandreturn,.save-ext').attr('disabled', false);
                var $formbottomlockforminfo = $('#formbottomlockforminfo');
                if ($formbottomlockforminfo.length) {
                    $formbottomlockforminfo.remove();
                }
                GLOBAL_taskFormHubDialog.closeDialog();
            }

            taskFormHub.client.onVersionChanged = function (serverVersion) {
                var currentVersion = parseInt($('#version').val());
                if (serverVersion > currentVersion) {
                    thatObserver.ToServerInvoke("GetVersionData", currentVersion);
                }
            }

            //taskFormHub.client.submitedForm = function (userId, userName, date, newVersion, submitedData) {
            taskFormHub.client.onVersionChangedData = function (userId, userName, date, newVersion, submitedData) {
                thatObserver.onVersionChangedData(userId, userName, date, newVersion, submitedData);
            }

            customFormAfterSubmitEx.push(function () {
                if ($('#blockschanged').length == 0) $taskform.append('<input type="hidden" id="blockschanged" name="blockschanged" />')
                var blocksChanged = getBlocksNameChanged();
                $('#blockschanged').val(blocksChanged.join(','));
            });

            //проверка что сейчас кто-то сохраняет форму
            customValidateEx.push(function () {
                //если нет соединения с сервером, то и сохранить нельзя
                if ($.connection.hub.state != $.signalR.connectionState.connected) {
                    return false;
                }
                else {
                    $('.formbottom').find('.taskFormHub-connectionLost').remove();
                }
                //условине что форма заблокирована есть в следующей проверке на стророне сервера
                return /*taskFormLockedByUser == undefined &&*/ thatObserver.conflictManager.isValid();
            });

            customValidateEx.push(function () {
                return thatObserver.CheckCanSubmitTaskForm();
            }); 
        }

        function getWorkflowStatuses() {
            $.ajax({
                url: 'Task/GetWorkflowStatuses',
                type: 'POST',
                data: {
                    taskId: $('#id').val(),
                    workflowId: $('#workflowid').val(),
                    serviceId: $('#serviceid').val()
                },
                dataType: 'json'
            }).done(function (result) {
                if (result) {
                    var $status = $('select#statusid');
                    $status.html(result.statusesString);
                    $status.attr("disabled", result.isBlocked).prop("disabled", result.isBlocked);
                }
            }).fail(function() {

            });
        }

        function serverFunctions() {
            if ($('#id').val() > 0) {
                $('.formbottom').append('<input type="hidden" class="checklocktaskform" name="checklocktaskform" value="' + $('#id').val() + '">');

                jQuery.validator.addMethod('input-conflict-block', function (value, element) {
                    return false;
                },'');

                //$taskform.data('validator').settings.rules = $.extend({}, $taskform.data('validator').settings.rules, {
                //    checklocktaskform: {
                //        required: true,
                //        remote: {
                //            url: 'Task/CanSubmitTaskForm',
                //            type: 'post',
                //            data: {
                //                taskId: $('#id').val(),
                //                connectionId: function () { return $.connection.hub.id; },
                //                changed: function () { return $('#changed').val() },
                //            }
                //        }
                //    },
                //    messages: {
                //        checklocktaskform: {
                //            remote: function () { return 'Форма была сохранена другим пользователем.<br>Пожалуйста проверьте блоки на конфликты'; }
                //        },
                //    },
                //});

                //jQuery.validator.addMethod('checklocktaskform', function (value, element) {
                //    var valid = false;
                //    $.ajax({
                //        url: 'Task/CanSubmitTaskForm',
                //        type: 'POST',
                //        async: false,
                //        data: {
                //            taskId: $('#id').val(),
                //            connectionId: function () { return $.connection.hub.id; },
                //            changed: function () { return $('#changed').val() },
                //        },
                //        //dataType: 'json',
                //        success: function (result) {
                //            valid = result == 'true';
                //        }
                //    }).fail(function () { valid = false; });
                //    return valid;
                //}, 'Форма была сохранена другим пользователем.<br>Пожалуйста проверьте блоки на конфликты');
            }

        }

        this.ToServerInvoke = function () {
            if (!hubStarted)
                return $.Deferred().reject(_hubNotStartedObject).promise();

            return taskFormHub.invoke.apply(taskFormHub, $.makeArray(arguments));
        }

        //function openOverlayDialog(data, options) {
        //    closeOverlayDialog();
        //    var $div = $('<div class="taskFormHub-overlaydialog"></div>');
        //    $div.append(data);
        //    $div.dialog($.extend({}, {
        //        modal: true,
        //        width: 'auto',
        //        buttons: {
        //            Ok: function () {
        //                $(this).dialog("close");
        //            }
        //        }
        //    }, options));
        //}

        //function closeOverlayDialog() {
        //    $(".taskFormHub-overlaydialog").dialog("close");
        //}

        //function openOverlay(data) {
        //    var $taskFormHub_overlay = $('.taskFormHub-overlay');
        //    if (!$taskFormHub_overlay.length) {
        //        $taskFormHub_overlay = $('<div class="taskFormHub-overlay userData2Overlay">');
        //        $taskFormHub_overlay.css({ 'position': 'fixed', 'width': '100%', 'height': '100%', 'top': '0px', 'left': '0px', 'display': 'block', 'background-color': '#000000', 'opacity': '0.5' });
        //        $('body').append($taskFormHub_overlay);
        //    }
        //    $taskFormHub_overlay.html(data);
        //}

        //function closeOverlay() {
        //    var $taskFormHub_overlay = $('.taskFormHub-overlay');
        //    if ($taskFormHub_overlay.length) {
        //        $taskFormHub_overlay.remove();
        //    }
        //    return false;
        //}

        this.conflictManager = new function () {
            var blocksChanged = {};
            var blocksConflict = [];
            this.init = function (userId, userName, date, submitedData) {
                taskFormSubmitedByUser = { userId: userId, userName: userName, date: date };
                blocksChanged = $.extend({}, blocksChanged, submitedData);
                blocksConflict = [];
                for (var blockName in blocksChanged) {
                    if (!blocksChanged.hasOwnProperty(blockName) || !_blocks[blockName]) {
                        continue;
                    }

                    if (_blocks[blockName].InitConflictAfterSubmit(blocksChanged[blockName])) {
                        blocksConflict.push(blockName);
                    }
                }
                return blocksConflict;
            }

            this.isValid = function () {
                if (taskFormSubmitedByUser == undefined || blocksConflict.length == 0) {
                    return true;
                }

                for (var i = 0; i < blocksConflict.length; i++) {
                    if (!_blocks[blocksConflict[i]].ConflictIsResolved(true)) {
                        return false;
                    }
                }
                    
                return true;
            }
        }

        return this;
    };

    GLOBAL_taskFormHubObserver = taskFormHubObserver;

    taskFormHubObserver.CheckCanSubmitTaskForm = function () {
        return true;
    }

    if ($('#id').val() > 0 && $('#taskFormHubIsEnable').val() == 'true') {

        taskFormHubObserver.CheckCanSubmitTaskForm = function () {
            var valid = false;
            $.ajax({
                url: 'Task/CanSubmitTaskForm',
                type: 'POST',
                async: false,
                data: {
                    taskId: $('#id').val(),
                    connectionId: function () { return $.connection.hub.id; },
                    //changed: function () { return $('#changed').val() },
                    formVersion: function () { return $('#version').val() }
                },
                dataType: 'json',
                success: function (result) {
                    if (result) {
                        valid = result.Can;
                        if (result.Data) {
                            //находит конфликты и обновляем блоки
                            var blocksConflict = GLOBAL_taskFormHubObserver.onVersionChangedData(result.EditorId, result.EditorName, result.Date, result.Version, result.Data);
                            //даже если от сервера пришел "result.Can == false", то мы можем продолжить сохранение если нет конфликтов
                            valid = blocksConflict.length == 0;
                        }
                    }
                    else {
                        valid = false;
                    }
                    //valid = result == 'true';
                }
            }).fail(function () { valid = false; });
            return valid;
        }

        GLOBAL_taskFormHubObserver.init();
    }
    
});