(function(app) {
    
    'use strict';
    
    var moduleName = 'Contacts';
    
    var sugar_token     = null;
    var sugar_refresh   = null;
    var username        = null;
    var usermail        = null;
    var settings        = null;
    var loaded          = false;
    
    /**
     * 
     * @returns {void}
     */
    var retrieveUsermail = function(callback) {
        app.api.call('read', app.api.buildURL('Users') + '/' + app.user.id, null, {
            success: function(response) {
                usermail = response['email1'];
                callback();
            }
        });
    };
    
    /**
     * 
     * @returns {void}
     */
    var retrieveSettings = function(callback) {
        app.api.call('read', app.api.buildURL('sp_api', 'getgeneralsettings'), null, {
            success: function(response) {
                settings = JSON.parse(response);
                callback();
            }
        });
    };
    
    /**
     * 
     * @param {array} recipients
     * @param {number} totalrecords
     * @param {string} url_api_read
     * @returns {void}
     */
    var showSendWizard = function(recipients, totalrecords, url_api_read) {
        var path    = Backbone.history.location.pathname + 'modules/SP_SendWizard/index.html';
        var name    = 'sp_sendwizard_' + (new Date().valueOf()).toString() + '_' + Math.ceil(Math.random() * 10000);
        var params  = 'scrollbars=yes,toolbar=no,location=no,width=900,height=800';
        
        var w = window.open(path, name, params);
        if (w === null) {
            console.log('Error: cannot open sendwizard window!');
            return;
        }

        w['current_user']   = app.user.id;
        w['sugar_token']    = app.api.getOAuthToken();
        w['sugar_refresh']  = app.api.getRefreshToken();
        w['username']       = app.user.get('full_name');
        w['usermail']       = usermail;
        w['auth_username']  = settings['sp_username'];
        w['auth_password']  = settings['sp_password'];
        
        w['url_api_getaccesstoken']         = app.api.buildURL('sp_api', 'getaccesstoken');
        w['url_api_getmailtemplatelist']    = app.api.buildURL('sp_api', 'getmailtemplatelist');
        w['url_api_getmetadatalist']        = app.api.buildURL('sp_api', 'getmetadatalist');
        w['url_api_getmailpreview']         = app.api.buildURL('sp_api', 'getmailpreview');
        w['url_api_schedulemail']           = app.api.buildURL('sp_api', 'schedulemail');
        w['url_api_addrecipients']          = app.api.buildURL('sp_api', 'addrecipientstoscheduledmail');
        w['url_api_commitmail']             = app.api.buildURL('sp_api', 'commitmail');
        w['url_api_addmailing']             = app.api.buildURL('sp_api', 'addmailing');
        w['url_api_refreshtoken']           = app.api.buildURL('oauth2/token');
        w['url_api_read']                   = url_api_read;

        w['language']                       = app.lang.getLanguage();
        w['recipients']                     = recipients;
        w['total_records']                  = totalrecords;
    };
    
    var createFilterArgsString = function(collection) {
        var argsFullString = '';
        var argsLapString = '';

        var filterIndex = 0;
        var arrayProcessing = false;
        var prevObjectProperty = '';

        function repackStringsArrayItem(rootItem, rootFilterProperty, prevObjectProperty) {
            //resave field level object key (lead_source)
            var rootFieldKey = prevObjectProperty;

            //go through all strings in item - 0:Existing Customer, 1:Cold Call, ...
            var repackedObjects = [];
            for (var i = 0; i < rootItem.length; i++) {
                var arrayItem = rootItem[i];

                //create new objects hierarchy
                var fieldObject = {};
                var operatorObject = {};
                var valueObject = {};

                //init key and data for new field object
                fieldObject[rootFieldKey] = operatorObject;

                //init key and new operator data object
                operatorObject[rootFilterProperty] = valueObject;

                //get key and data for new value object
                var tempValueKey = Object.keys(rootItem)[i];
                var tempValueData = arrayItem;

                //init key and data for new value object
                valueObject[tempValueKey] = tempValueData;

                //Final object to process
                var repackedObject = i > 0 ? fieldObject : operatorObject;

                repackedObjects.push(repackedObject);
            }
            return repackedObjects;
        }

        function repackObjectsArrayItem(rootItem, rootFilterProperty) {
            //save operator level object key ($or/$and)
            var operatorFieldKey = rootFilterProperty;

            //go through all objects {Index}:{Object}
            var repackedObjects = [];
            for (var i = 0; i < rootItem.length; i++) {
                var arrayItem = rootItem[i];

                //create new object hierarchy
                var operatorObject = {};
                var indexObject = {};

                //init key and data for new operator object
                operatorObject[operatorFieldKey] = indexObject;

                //init key and data for new index object
                indexObject[i] = arrayItem;

                //Final object to process
                var repackedObject = operatorObject;

                repackedObjects.push(repackedObject);
            }
            return repackedObjects;
        }

        //returns - 1 == Object, 2 == Array, 3 == String,  -1 == Exception
        function getFilterType(filter) {
            var type;

            //used Object.prototype.toString.call() because typeof returns same string - "Object" for Object and Array types
            var filterTypeString = Object.prototype.toString.call(filter);
            switch (filterTypeString) {
                case '[object Object]':
                    type = 1;
                    break;
                case '[object Array]':
                    type = 2;
                    break;
                case '[object String]':
                    type = 3;
                    break;
                default:
                    type = -1;
            }
            return type;
        }

        function processFilter(filters, func) {
            for (var filterProperty in filters) {
                var filterData = filters[filterProperty];
                var filterDataType = getFilterType(filterData);

                //Processing Object type
                if (filterDataType === 1) {
                    //Don't change root filterProperty (for example lead source) if processing array
                    if (!arrayProcessing) {
                        //Need that in case value in object is Array
                        prevObjectProperty = filterProperty;
                    }

                    //Adding property to lap string
                    argsLapString += '[' + filterProperty + ']';

                    //process next filter
                    func.apply(this, [filters[filterProperty], func]);
                }
                    //Processing Array type
                else if (filterDataType === 2) {
                    arrayProcessing = true;

                    //todo - think what to do if array is empty ???
                    if (filterData.length === 0) {
                        return;
                    }

                    var arrayFilterDataType = getFilterType(filterData[0]);

                    //"IS BETWEEN", "IS ANY OF" or "IS NOT ANY OF" arrays (LeadSource or DateRange)
                    //Processing string items inside array
                    if (arrayFilterDataType === 3) {
                        //repack strings
                        var repackedObjects = repackStringsArrayItem(filterData, filterProperty, prevObjectProperty);

                        //Process all repacked objects
                        for (var repackedObjectProperty in repackedObjects) {
                            func.apply(this, [repackedObjects[repackedObjectProperty], func]);
                        }
                    }
                        //"STARTS WITH" or "IS" for arrays like Phone 
                        //Processing array items inside array
                    else if (arrayFilterDataType === 1) {
                        //repack objects
                        var repackedObjects = repackObjectsArrayItem(filterData, filterProperty);

                        //Process all repacked objects
                        for (var repackedObjectProperty in repackedObjects) {
                            func.apply(this, [repackedObjects[repackedObjectProperty], func]);
                        }
                    }

                    //Increment main index when array processing is done
                    filterIndex++;
                    arrayProcessing = false;
                }
                    //Processing String type (hope the last element in filter) 
                else if (filterDataType === 3) {
                    //build final string
                    argsFullString += '&filter[' + filterIndex + ']';
                    argsFullString += argsLapString;
                    argsFullString += '[' + filterProperty + ']=' + filterData;

                    argsLapString = '';
                    //working on same filter do not increment main index
                    if (arrayProcessing) {
                        return;
                    }

                    //increment filter index for next filter
                    filterIndex++;
                }
            }
        }

        var filtersDefinition = collection.filterDef;
        for (var filterDefinitionKey in filtersDefinition) {
            processFilter(filtersDefinition[filterDefinitionKey], processFilter);
        }
        return argsFullString;
    };
    
    app.events.on('app:sync:complete', function() {
        
        if (loaded) { return; }
        loaded = true;
        
        sugar_token     = app.api.getOAuthToken();
        sugar_refresh   = app.api.getRefreshToken();
        username        = app.user.get('full_name');
        
        app.router.on('route:record', function(module, id) {
            if (module === moduleName) {

                $("a[name='sp_sendsilverpopemail']").attr('disabled', 'disabled');
                
                $.ajax("rest/v10/Contacts/" + id, { "headers": { "OAuth-Token": app.api.getOAuthToken() } }).then(function(response) {
                    if (response.sp_synctosilverpop == true) {
                        $("a[name='sp_sendsilverpopemail']").removeAttr("disabled");

                        app.controller.context.on('button:sp_sendsilverpopemail:click', function (model) {
                            var recipients = [{'sync_id': model.get('id'), 'engage_id': model.get('sp_engageid')}];
                            showSendWizard(recipients, 1, '');
                        });
                    } else {
                        $("a[name='sp_sendsilverpopemail']").attr("disabled", "disabled");
                    }
                });

                retrieveUsermail(function() {
                    retrieveSettings(function() {
                    });
                });
            }
        });
        
        app.router.on('route:list', function(module) {
            if (module === moduleName) {

                $("a[name='sp_sendsilverpopemail']").attr('disabled', 'disabled');

                retrieveUsermail(function() {
                    retrieveSettings(function() {
                        $("a[name='sp_sendsilverpopemail']").removeAttr("disabled");
                    });
                });
                
                app.controller.context.on('button:sp_sendsilverpopemail:click', function(model) {
                    var self        = this;
                    var selected    = this.get('mass_collection');
                    var collection  = this.get('collection');
                    var recipients  = [];
                    
                    if (selected.length === 0) {
                        var filter = null;
                        if (collection.filterDef.length > 0) {
                            filter = {
                                "filter": []
                            };

                            for (var i = 0; i < collection.filterDef.length; i++) {
                                filter['filter'].push(collection.filterDef[i]);
                            }
                        }

                        var totalRecords = 0;
                        var filterParams = createFilterArgsString(collection);

                        app.api.call('read', app.api.buildURL(moduleName, null, null, null) + '/count?offset=0' + filterParams, null, {
                            success: function(data) {
                                totalRecords = data['record_count'];
                                
                                var filterParams = (filter === null ? '/filter?fields=id,sp_engageid,sp_synctosilverpop' : '&fields=id,sp_engageid,sp_synctosilverpop');
                                var url_api_read = app.api.buildURL(moduleName, null, null, filter) + filterParams;

                                showSendWizard(recipients, totalRecords, url_api_read);
                            },
                            error: function() {
                                alert('Unexpected error!');
                            }
                        });
                    } else {
                        for (var i = 0; i < selected.length; i++) {
                            if (selected.models[i].get('sp_synctosilverpop') === true) {
                                recipients.push({
                                    'sync_id': selected.models[i].get('id'),
                                    'engage_id': selected.models[i].get('sp_engageid')
                                });
                            }
                        }

                        showSendWizard(recipients, recipients.length, '');
                    }
                    
                });
            }
        });
        
    });
    
    app.events.on('app:view:change', function(module, self) {
        if (module === 'merge-duplicates') {
            
            var collection = self.selectedDuplicates;
            if (collection.length > 0) {
                
                var recs = [];
                
                for (var i = 0; i < collection.length; i++) {
                    recs.push(collection[i].get('id'));
                    collection[i].set({ 'sp_frommerge': 'yes' });
                }
                
                // Here the self.primary is always null
                if (self.primary === null) { self.primary = collection[0]; }
                self.primary.set({ 'sp_slaverecs': recs });
            }
        }
    });
    
})(SUGAR.App);
