/**
 *  map settings dialogs
 */

define([
    'jquery',
    'app/init',
    'app/util',
    'app/render',
    'bootbox',
    'app/ccp'
], function($, Init, Util, Render, bootbox, CCP) {
    'use strict';

    var config = {
        // map dialog
        newMapDialogId: 'pf-map-dialog',                                                // id for map settings dialog
        dialogMapCreateContainerId: 'pf-map-dialog-create',                             // id for the "new map" container
        dialogMapEditContainerId: 'pf-map-dialog-edit',                                 // id for the "edit" container
        dialogMapSettingsContainerId: 'pf-map-dialog-settings',                         // id for the "settings" container
        dialogMapDownloadContainerId: 'pf-map-dialog-download',                         // id for the "download" container

        userSelectId: 'pf-map-dialog-user-select',                                      // id for "user" select
        corporationSelectId: 'pf-map-dialog-corporation-select',                        // id for "corporation" select
        allianceSelectId: 'pf-map-dialog-alliance-select',                              // id for "alliance" select

        dialogMapExportFormId: 'pf-map-dialog-form-export',                             // id for "export" form
        dialogMapImportFormId: 'pf-map-dialog-form-import',                             // id for "import" form

        buttonExportId: 'pf-map-dialog-button-export',                                  // id for "export" button
        buttonImportId: 'pf-map-dialog-button-import',                                  // id for "import" button

        fieldExportId: 'pf-map-filename-export',                                        // id for "export" filename field
        fieldImportId: 'pf-map-filename-import',                                        // id for "import" filename field
        dialogMapImportInfoId: 'pf-map-import-container',                               // id for "info" container
        dragDropElementClass: 'pf-form-dropzone'                                        // class for "drag&drop" zone
    };

    /**
     * format a given string into a valid filename
     * @param filename
     * @returns {string}
     */
    var formatFilename = function(filename){
        filename = filename.replace(/[^a-zA-Z0-9]/g,'_');

        var nowDate = new Date();
        var filenameDate = nowDate.toISOString().slice(0,10).replace(/-/g, '_');

        return  (filename + '_' + filenameDate).replace(/__/g,'_');
    };

    /**
     * shows the add/edit map dialog
     * @param mapData
     * @param options
     */
    $.fn.showMapSettingsDialog = function(mapData, options){

        // check if dialog is already open
        var mapInfoDialogElement = $('#' + config.newMapDialogId);
        if(!mapInfoDialogElement.is(':visible')){

            requirejs([
                'text!templates/dialog/map.html',
                'text!templates/form/map_settings.html',
                'mustache'
            ], function(templateMapDialog, templateMapSettings, Mustache) {

                var dialogTitle = 'Map settings';

                // if there are no maps -> hide settings tab
                var hideSettingsTab = false;
                var hideEditTab = false;
                var hideDownloadTab = false;

                if(mapData === false){
                    hideSettingsTab = true;
                    hideEditTab = true;
                    hideDownloadTab = true;
                }

                // available map "types" for a new or existing map
                var mapTypes = Util.getMapTypes(true);

                var data = {
                    scope: Util.getMapScopes(),
                    type: mapTypes,
                    icon: Util.getMapIcons(),
                    formErrorContainerClass: Util.config.formErrorContainerClass,
                    formWarningContainerClass: Util.config.formWarningContainerClass,
                    formInfoContainerClass: Util.config.formInfoContainerClass
                };

                // render "new map" tab content -------------------------------------------
                var contentNewMap = Mustache.render(templateMapSettings, data);

                // render "edit map" tab content ------------------------------------------
                var contentEditMap = Mustache.render(templateMapSettings, data);
                contentEditMap = $(contentEditMap);

                // current map access info
                var accessUser = [];
                var accessCorporation = [];
                var accessAlliance = [];

                if(mapData !== false){
                    // set current map information
                    contentEditMap.find('input[name="id"]').val( mapData.config.id );
                    contentEditMap.find('select[name="icon"]').val( mapData.config.icon );
                    contentEditMap.find('input[name="name"]').val( mapData.config.name );
                    contentEditMap.find('select[name="scopeId"]').val( mapData.config.scope.id );
                    contentEditMap.find('select[name="typeId"]').val( mapData.config.type.id );

                    accessUser = mapData.config.access.user;
                    accessCorporation = mapData.config.access.corporation;
                    accessAlliance = mapData.config.access.alliance;
                }

                // render main dialog -----------------------------------------------------
                data = {
                    id: config.newMapDialogId,
                    mapData: mapData,
                    type: mapTypes,
                    isInGameBrowser: CCP.isInGameBrowser(),

                    // message container
                    formErrorContainerClass: Util.config.formErrorContainerClass,
                    formWarningContainerClass: Util.config.formWarningContainerClass,
                    formInfoContainerClass: Util.config.formInfoContainerClass,

                    // default open tab ----------
                    openTabNew: options.tab === 'new',
                    openTabEdit: options.tab === 'edit',
                    openTabSettings: options.tab === 'settings',
                    openTabDownload: options.tab === 'download',

                    dialogMapCreateContainerId: config.dialogMapCreateContainerId,
                    dialogMapEditContainerId: config.dialogMapEditContainerId,
                    dialogMapSettingsContainerId: config.dialogMapSettingsContainerId,
                    dialogMapDownloadContainerId: config.dialogMapDownloadContainerId,

                    hideEditTab: hideEditTab,
                    hideSettingsTab: hideSettingsTab,
                    hideDownloadTab: hideDownloadTab,

                    // settings tab --------------
                    userSelectId: config.userSelectId,
                    corporationSelectId: config.corporationSelectId,
                    allianceSelectId: config.allianceSelectId,

                    // map access objects --------
                    accessUser: accessUser,
                    accessCorporation: accessCorporation,
                    accessAlliance: accessAlliance,

                    // access limitations --------
                    maxUser: Init.maxSharedCount.user,
                    maxCorporation: Init.maxSharedCount.corporation,
                    maxAlliance: Init.maxSharedCount.alliance,

                    // download tab --------------
                    dialogMapExportFormId: config.dialogMapExportFormId,
                    dialogMapImportFormId: config.dialogMapImportFormId,
                    buttonExportId: config.buttonExportId,
                    buttonImportId: config.buttonImportId,
                    fieldExportId: config.fieldExportId,
                    fieldImportId: config.fieldImportId,
                    dialogMapImportInfoId: config.dialogMapImportInfoId,

                    formatFilename: function(){
                        // format filename from "map name" (initial)
                        return function (mapName, render) {
                            var filename = render(mapName);
                            return formatFilename(filename);
                        };
                    }
                };

                var contentDialog = Mustache.render(templateMapDialog, data);
                contentDialog = $(contentDialog);

                // set tab content
                $('#' + config.dialogMapCreateContainerId, contentDialog).html(contentNewMap);
                $('#' + config.dialogMapEditContainerId, contentDialog).html(contentEditMap);

                // disable modal focus event -> otherwise select2 is not working! -> quick fix
                $.fn.modal.Constructor.prototype.enforceFocus = function() {};

                var mapInfoDialog = bootbox.dialog({
                    title: dialogTitle,
                    message: contentDialog,
                    buttons: {
                        close: {
                            label: 'cancel',
                            className: 'btn-default'
                        },
                        success: {
                            label: '<i class="fa fa-check fa-fw"></i>&nbsp;save',
                            className: 'btn-success',
                            callback: function() {

                                // get the current active form
                                var form = $('#' + config.newMapDialogId).find('form').filter(':visible');

                                // validate form
                                form.validator('validate');

                                // validate select2 fields (settings tab)
                                form.find('select').each(function(){
                                    var selectField = $(this);
                                    var selectValues = selectField.val();

                                    if(selectValues === null){
                                        selectField.parents('.form-group').addClass('has-error');
                                    }else{
                                        selectField.parents('.form-group').removeClass('has-error');
                                    }
                                });

                                // check weather the form is valid
                                var formValid = form.isValidForm();

                                if(formValid === true){

                                    // lock dialog
                                    var dialogContent = mapInfoDialog.find('.modal-content');
                                    dialogContent.showLoadingAnimation();

                                    var newMapData = {formData: form.getFormValues()};

                                    $.ajax({
                                        type: 'POST',
                                        url: Init.path.saveMap,
                                        data: newMapData,
                                        dataType: 'json'
                                    }).done(function(responseData){

                                        dialogContent.hideLoadingAnimation();

                                        if(responseData.error.length){
                                            form.showFormMessage(responseData.error);
                                        }else{
                                            // success
                                            Util.showNotify({title: dialogTitle, text: 'Map: ' + responseData.mapData.mapData.name, type: 'success'});

                                            // update map-tab Element
                                            var tabLinkElement = Util.getMapModule().getMapTabElements(responseData.mapData.mapData.id);
                                            if(tabLinkElement.length === 1){
                                                tabLinkElement.updateTabData(responseData.mapData.mapData);
                                            }

                                            $(mapInfoDialog).modal('hide');
                                            $(document).trigger('pf:closeMenu', [{}]);
                                        }
                                    }).fail(function( jqXHR, status, error) {
                                        var reason = status + ' ' + error;
                                        Util.showNotify({title: jqXHR.status + ': saveMap', text: reason, type: 'warning'});
                                        $(document).setProgramStatus('problem');

                                    });
                                }

                                return false;
                            }
                        }
                    }
                });


                // after modal is shown =======================================================================
                mapInfoDialog.on('shown.bs.modal', function(e){

                    mapInfoDialog.initTooltips();

                    // prevent "disabled" tabs from being clicked... "bootstrap" bugFix...
                    mapInfoDialog.find('.navbar a[data-toggle=tab]').on('click', function(e){
                        if ($(this).hasClass('disabled')){
                            e.preventDefault();
                            return false;
                        }
                    });

                    // set form validator
                    mapInfoDialog.find('form').initFormValidation();

                    // events for tab change
                    mapInfoDialog.find('.navbar a').on('shown.bs.tab', function(e){

                        var selectElementUser = mapInfoDialog.find('#' + config.userSelectId);
                        var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
                        var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);

                        if($(e.target).attr('href') === '#' + config.dialogMapSettingsContainerId){
                            // "settings" tab
                            initSettingsSelectFields(mapInfoDialog);
                        }else{
                            if( $(selectElementUser).data('select2') !== undefined ){
                                $(selectElementUser).select2('destroy');
                            }

                            if( $(selectElementCorporation).data('select2') !== undefined ){
                                $(selectElementCorporation).select2('destroy');
                            }

                            if( $(selectElementAlliance).data('select2') !== undefined ){
                                $(selectElementAlliance).select2('destroy');
                            }
                        }

                        // no "save" dialog  button on "in/export" tab
                        if($(e.target).attr('href') === '#' + config.dialogMapDownloadContainerId){
                            mapInfoDialog.find('button.btn-success').hide();
                        }else{
                            mapInfoDialog.find('button.btn-success').show();
                        }
                    });

                    // show form messages -------------------------------------
                    // get current active form(tab)
                    var form = $('#' + config.newMapDialogId).find('form').filter(':visible');

                    form.showFormMessage([{type: 'info', message: 'Creating new maps or change settings may take a few seconds'}]);

                    if(mapData === false){
                        // no map data found (probably new user
                        form.showFormMessage([{type: 'warning', message: 'No maps found. Create a new map before you can start'}]);
                    }

                    // init select fields in case "settings" tab is open by default
                    if(options.tab === 'settings'){
                        initSettingsSelectFields(mapInfoDialog);
                    }

                    // init "download tab" ========================================================================
                    var downloadTabElement = mapInfoDialog.find('#' + config.dialogMapDownloadContainerId);
                    if(downloadTabElement.length){
                        // tab exists

                        // export map data ------------------------------------------------------------------------
                        downloadTabElement.find('#' + config.buttonExportId).on('click', { mapData: mapData }, function(e){

                            var exportForm = $('#' + config.dialogMapExportFormId);
                            var validExportForm = exportForm.isValidForm();

                            if(validExportForm){
                                // set map data right before download
                                $(this).setExportMapData(e.data.mapData);
                            }else{
                                e.preventDefault();
                            }
                        });

                        // import map data ------------------------------------------------------------------------
                        // check if "FileReader" API is supported
                        var importFormElement = downloadTabElement.find('#' + config.dialogMapImportFormId);
                        if(window.File && window.FileReader && window.FileList && window.Blob){

                            // show file info in UI
                            downloadTabElement.find('#' + config.fieldImportId).on('change', function(e){
                                e.stopPropagation();
                                e.preventDefault();

                                var infoContainerElement = importFormElement.find('#' + config.dialogMapImportInfoId);
                                infoContainerElement.hide().empty();
                                importFormElement.hideFormMessage('all');

                                var output = [];
                                var files = e.target.files;

                                for (var i = 0, f; !!(f = files[i]); i++) {
                                    output.push(( i + 1 ) + '. file: ' + f.name + ' - ' +
                                        f.size + ' bytes; last modified: ' +
                                        f.lastModifiedDate.toLocaleDateString() );
                                }

                                if(output.length > 0){
                                    infoContainerElement.html( output ).show();
                                }

                                importFormElement.validator('validate');
                            });

                            // drag&drop
                            var importData = {};
                            importData.mapData = [];
                            var files = [];
                            var filesCount = 0;
                            var filesCountFail = 0;

                            // onLoad for FileReader API
                            var readerOnLoad = function(readEvent) {

                                // get file content
                                try{
                                    importData.mapData.push( JSON.parse( readEvent.target.result ) );
                                }catch(error){
                                    filesCountFail++;
                                    importFormElement.showFormMessage([{type: 'error', message: 'File can not be parsed'}]);
                                }

                                // start import when all files are parsed
                                if(
                                    filesCount === files.length &&
                                    filesCountFail === 0
                                ){
                                    importMaps(importData);
                                }
                            };

                            var handleDragOver = function(dragEvent) {
                                dragEvent.stopPropagation();
                                dragEvent.preventDefault();
                                dragEvent.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
                            };

                            var handleFileSelect = function(evt){
                                evt.stopPropagation();
                                evt.preventDefault();

                                importData = importFormElement.getFormValues();
                                importData.mapData = [];
                                filesCount = 0;
                                filesCountFail = 0;

                                files = evt.dataTransfer.files; // FileList object.

                                for (var file; !!(file = files[filesCount]); filesCount++){
                                    var reader = new FileReader();
                                    reader.onload = readerOnLoad;
                                    reader.readAsText(file);
                                }
                            };

                            var dropZone = downloadTabElement.find('.' + config.dragDropElementClass);
                            dropZone[0].addEventListener('dragover', handleDragOver, false);
                            dropZone[0].addEventListener('drop', handleFileSelect, false);

                            // import "button"
                            downloadTabElement.find('#' + config.buttonImportId).on('click', function(e) {

                                importFormElement.validator('validate');
                                var validImportForm = importFormElement.isValidForm();

                                if(validImportForm){
                                    importData = importFormElement.getFormValues();
                                    importData.mapData = [];

                                    var fileElement = downloadTabElement.find('#' + config.fieldImportId);
                                    files = fileElement[0].files;
                                    filesCount = 0;
                                    filesCountFail = 0;

                                    for (var file; !!(file = files[filesCount]); filesCount++){
                                        var reader = new FileReader();
                                        reader.onload = readerOnLoad;
                                        reader.readAsText(file);
                                    }
                                }
                            });
                        }else{
                            importFormElement.showFormMessage([{type: 'error', message: 'The File APIs are not fully supported in this browser.'}]);
                        }
                    }
                });
            });
        }
    };

    /**
     * import new map(s) data
     * @param importData
     */
    var importMaps = function(importData){

        var importForm = $('#' + config.dialogMapImportFormId);
        importForm.hideFormMessage('all');

        // lock dialog
        var dialogContent = importForm.parents('.modal-content');
        dialogContent.showLoadingAnimation();

        $.ajax({
            type: 'POST',
            url: Init.path.importMap,
            data: importData,
            dataType: 'json'
        }).done(function(responseData){
            if(responseData.error.length){
                //   form.showFormMessage(responseData.error);
                importForm.showFormMessage(responseData.error);
            }else{
                // success

                Util.showNotify({title: 'Import finished', text: 'Map(s) imported', type: 'success'});
            }
        }).fail(function( jqXHR, status, error) {
            var reason = status + ' ' + error;
            Util.showNotify({title: jqXHR.status + ': importMap', text: reason, type: 'error'});
        }).always(function() {
            importForm.find('input, select').resetFormFields().trigger('change');
            dialogContent.hideLoadingAnimation();
        });
    };

    /**
     * set json map data for export to an element (e.g. <a>-Tag or button) for download
     * @param mapData
     * @returns {*}
     */
    $.fn.setExportMapData = function(mapData){

        var fieldExport = $('#' + config.fieldExportId);
        var filename = '';
        var mapDataEncoded = '';

        if(fieldExport.length){
            filename = fieldExport.val();

            if(filename.length > 0){
                // remove object properties that should not be included in export
                // -> e.g. jsPlumb object,...
                var allowedKeys = ['config', 'data'];

                var replace = function(obj, keys) {
                    var dup = {};
                    for (var key in obj) {
                        if (keys.indexOf(key) !== -1) {
                            dup[key] = obj[key];
                        }
                    }
                    return dup;
                };

                mapDataEncoded = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify( replace(mapData, allowedKeys) ));
            }
        }

        return this.each(function(){
            var exportButton = $(this);
            exportButton.attr('href', 'data:' + mapDataEncoded);
            exportButton.attr('download', filename + '.json');
        });
    };


    /**
     * init select2 fields within the settings dialog
     * @param mapInfoDialog
     */
    var initSettingsSelectFields = function(mapInfoDialog){

        var selectElementUser = mapInfoDialog.find('#' + config.userSelectId);
        var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
        var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);

        // init corporation select live search
        selectElementUser.initAccessSelect({
            type: 'user',
            maxSelectionLength: Init.maxSharedCount.user
        });

        // init corporation select live search
        selectElementCorporation.initAccessSelect({
            type: 'corporation',
            maxSelectionLength: Init.maxSharedCount.corporation
        });

        // init alliance select live search
        selectElementAlliance.initAccessSelect({
            type: 'alliance',
            maxSelectionLength: Init.maxSharedCount.alliance
        });
    };

    /**
     * shows the delete map Dialog
     * @param mapElement
     */
    $.fn.showDeleteMapDialog = function(mapData){

        var mapName = mapData.config.name;

        var mapDeleteDialog = bootbox.confirm('Delete map "' + mapName + '"?', function(result){
            if(result){

                var data = {mapData: mapData.config};

                $.ajax({
                    type: 'POST',
                    url: Init.path.deleteMap,
                    data: data,
                    dataType: 'json'
                }).done(function(data){
                    Util.showNotify({title: 'Map deleted', text: 'Map: ' + mapName, type: 'success'});

                    $(mapDeleteDialog).modal('hide');
                }).fail(function( jqXHR, status, error) {
                    var reason = status + ' ' + error;
                    Util.showNotify({title: jqXHR.status + ': deleteMap', text: reason, type: 'warning'});
                    $(document).setProgramStatus('problem');
                });

                return false;
            }
        });

    };


});