// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.

define(['hp/core/Localizer',
        'hp/core/Environment',
        'hp/core/Notifications',
        'hp/core/EventDispatcher',
        'hp/core/UnitConversion',
        'hp/services/Log',
        'text!hpPages/core/file_chooser_template.html',
        'text!hpPages/core/file_chooser_kiosk_template.html',
        'jquery'],
function(localizer, environment, notifications, EventDispatcher, unitConversion, Log, rawTemplate, kioskTemplate) {
"use strict";

    (function($) {
        // jQuery plugin definition

        // You can describe the control completely in HTML or
        // by passing in configuration options here, for example:
        $.fn.hpFileChooser = function(options) {

            var TEMPLATE = '.hp-file-chooser-container';
            var SECTION = '.hp-file-chooser';
            var FILE_CHOOSE = '.hp-file-chooser-file';
            var MESSAGE = '.hp-message';
            var FILE_SIZE = '.hp-file-chooser-file-size';
            var LABEL = '#hp-file-chooser-file-label';
            var ERROR_MESSAGE = "#hp-file-chooser-error-message";
            var DISCLAIMER_MESSAGE = "#hp-file-chooser-disclaimer-message";

            var instance;

            function hpFileChooser(elem) {

                var container;
                var template;
                var useForm = false;
                var label = null;
                var defaultMessage;
                
                /** 
                 * For security, file chooser's files attribute cannot be overwritten.
                 * It will need to stored as a local variable.
                 * See also: http://stackoverflow.com/questions/5632629/how-to-change-the-file-inputs-filelist
                 */
                var selectedFiles;
                
                /**
                 * Used to track if the drag and drop item is moving inside the file chooser 
                 */
                var isDragInsideChildComponent = false;
                
                /**
                 * Called when file is selected or deseleted, if defined.
                 */
                var onFileSelection;
                
                function clearDisclaimerMessage() {
                    $(DISCLAIMER_MESSAGE, container).empty();
                }
                
                function clearErrorMessage() {
                    $(ERROR_MESSAGE, container).empty();
                }
    
                function showErrorMessage(msg) {
                    clearDisclaimerMessage();
                    $(ERROR_MESSAGE, container).empty().text(msg);
                }

                this.showError = function (msg) {
                    showErrorMessage(msg);
                }

                function noOpDragAndDrop(e) {
                    e.stopPropagation();
                    e.preventDefault();
                }
    
                function trimFilename(filepath) {
                    // get rid of whitespace on the ends and pull of the filename from the end (allows either \ or / as separators.)
                    var parts = $.trim(filepath).split(/[\\\/]/);
                    return parts.length > 0 ? parts[parts.length - 1] : filepath;
                }

                /*
                 * Get the selected files directly from DOM
                 */
                function getFilesFromDOM() {
                    var fileElem = $(FILE_CHOOSE, container)[0];
                    var files;
                    if (fileElem.value) {
                        files = fileElem.files;
                        if (!files) {
                            // probably IE8 or IE9
                            files = [{ name: trimFilename(fileElem.value),
                                      size: undefined }]; // Not possible in IE<10 without ActiveX
                        }
                    } else {
                        files = [];
                    }
                    return files;
                }

                /*
                 * Format the file size in bytes to either KB, MB or GB
                 */
                function formatFilesize(size) {
                    var normalized = unitConversion.normalizeBytesSigFigs(size, 3);
                    var formattedSize = '' + normalized.value + ' ' +
                        localizer.getString('core.units.' + normalized.units);
                    return formattedSize;
                }                
                
                function getFileName() {
                    var name;
                    if (selectedFiles && selectedFiles[0]) {
                        name = selectedFiles[0].name;
                    }
                    return name;
                }
                
                function clearFileInput() {
                    $(FILE_CHOOSE, container).attr('dropped-file', '');
                    $(FILE_CHOOSE, container).trigger('change');
                }

                function getOptions() {
                    var options = {};
                    //Abe add this check
                    if (useForm) {
                        //options.useForm = useForm;
                        options.fileinput = $(FILE_CHOOSE, container);
                    }
                    options.files = selectedFiles;
                    return options;
                }
                
                function showDisclaimerMessage() {
                    var floatVersion = parseFloat($.browser.version);
                    clearErrorMessage();
                    if ($.browser.msie) {
                        if (floatVersion === 8) {
                            $(DISCLAIMER_MESSAGE, container).text(localizer.getString('core.file.chooser.disclaimerMessage', [2]));
                        }
                        else {
                            $(DISCLAIMER_MESSAGE, container).text(localizer.getString('core.file.chooser.disclaimerMessage', [4]));
                        }
                    }
                }

                function selectForUpload() {
                    var files = selectedFiles;
                    
                    if (files.length > 0) {
                        clearErrorMessage();
                        var filesize = files[0] && files[0].size ? formatFilesize(files[0].size) : '';
                        $(FILE_SIZE, container).empty().text(filesize).show();
                        $(MESSAGE, container).empty().text(files[0].name).show();
                        showDisclaimerMessage();
                    }
                    if (onFileSelection) {
                        onFileSelection.call(this, {files: files, options: getOptions()});
                    }
                }
                
                function toggleChooseButton(enabled) {
                    if (enabled) {
                        $(MESSAGE, container).text(localizer.getString('core.file.chooser.dragAndDrop'));
                        $('.hp-file-chooser-mask-container', container).css("visibility", "");
                        $('.hp-file-chooser-file-size', container).css("visibility", "");
                    } else {
                        $(MESSAGE, container).text(localizer.getString('core.file.chooser.dragOverText'));
                        $('.hp-file-chooser-mask-container', container).css("visibility", "hidden");
                        $('.hp-file-chooser-file-size', container).css("visibility", "hidden");
                    }
                }
                
                function toggleDragoverClass(enabled) {
                    if (enabled) {
                    	$(MESSAGE, container).removeClass("hp-help");
                        $(SECTION, container).addClass("hp-file-chooser-dragover");
                    } else {
                        $(SECTION, container).removeClass("hp-file-chooser-dragover");
                        // Remove if previously added
                        $(SECTION, container).removeClass("hp-file-multiple-dragover");
                    }
                    toggleChooseButton(!enabled);
                }
                
                function toggleDropClass(enabled) {
                    if (enabled) {
                    	$(SECTION, container).removeClass("hp-file-chooser-dragover");
                        $(SECTION, container).addClass("hp-file-chooser-dropped");
                    } else {
                        $(SECTION, container).removeClass("hp-file-chooser-dropped");   
                    }
                }
                
                function resetDropZoneMessage() {
                    var dropZoneTextKey = useForm ? 'core.file.chooser.browse_only' : 'core.file.chooser.dragAndDrop';
                    $(MESSAGE, container).text(localizer.getString(dropZoneTextKey));
                }
                
                function resetPreviousFileName() {
                    // Restore selected filename, if available
                    var name = getFileName();
                    if (name) {
                        $(MESSAGE, container).empty().text(name).show();
                    } else {
                        $(MESSAGE, container).addClass("hp-help");
                    }                	
                }

                function onDragEnter(event) {
                    if ($(event.target).parents(SECTION).length != 0) {
                        isDragInsideChildComponent = true;
                    } else {
                        isDragInsideChildComponent = false;
                        toggleDragoverClass(true);
                        toggleDropClass(false);
                    }
                    var eventObj = event.originalEvent ? event.originalEvent : event;
                    var dt = eventObj.dataTransfer;
                    if (dt && ((dt.items && dt.items.length > 1) ||
                        (dt.files && dt.files.length > 1) ||
                        (dt.mozItemCount && dt.mozItemCount > 1))) { // Firefox
                        $(MESSAGE, container).text(localizer.getString('core.file.chooser.dropOneFileOnly'));
                        $(SECTION, container).removeClass("hp-file-chooser-dragover");
                        $(SECTION, container).addClass("hp-file-multiple-dragover");
                    }
                    event.stopPropagation();
                    event.preventDefault();
                }
                
                function onDragLeave(event) {
                    if ($(event.target).parents(SECTION).length == 0) {
                        if (!isDragInsideChildComponent) {
                            toggleDragoverClass(false);
                            resetPreviousFileName();
                        }
                    } else {
                        isDragInsideChildComponent = false;
                    }
                    event.stopPropagation();
                    event.preventDefault();
                }
                
                function onDrop(e) {
                    
                    var droppedFiles = null;
                    var dataTransfer = null;

                    toggleChooseButton(true);
                    toggleDropClass(true);
                    
                    if (e.originalEvent && e.originalEvent.dataTransfer) {
                        droppedFiles = e.originalEvent.dataTransfer.files;
                        dataTransfer = e.originalEvent.dataTransfer;
                    } else if (e.dataTransfer) {
                        droppedFiles = e.dataTransfer.files;
                        dataTransfer = e.dataTransfer;
                    }

                    if (dataTransfer) {
                        e.stopPropagation();
                        e.preventDefault();
                        
                        if (droppedFiles) {
                            if(droppedFiles.length === 1) {
                                selectedFiles = droppedFiles;
                                selectForUpload();
                                $(FILE_CHOOSE, container).attr('dropped-file', droppedFiles[0].name);
                                $(FILE_CHOOSE, container).trigger('change');
                            } else if (droppedFiles.length > 1) {
                                // Restore previous chosen file name when multiple files are dropped.
                                toggleDragoverClass(false);
                                resetPreviousFileName();
                                // No error message
                            }
                        } else {
                            $(MESSAGE, container).empty().text(defaultMessage).show();
                            showErrorMessage(localizer.getString('core.file.chooser.noDragDrop'));
                            clearFileInput();
                        }
                    }
                }
                
                function changeHandler(e) {
                    var attr = $(FILE_CHOOSE, container).attr('dropped-file');
                    if (typeof attr !== 'undefined' && attr !== false) {
                        // if 'dropped-file' attribute exists on the element, then the change
                        // event is triggered event by drag/drop, don't process it here, just
                        // let it bubble up to formStateVew.
                        return;
                    }
                    selectedFiles = getFilesFromDOM();
                    $(SECTION, container).addClass("hp-file-chooser-dropped");
                    $(MESSAGE, container).removeClass("hp-help");
                    selectForUpload();
                }
                
                function setLabel(id) {
                    var labelElmt = $('label[for=' + id + '], label[data-name=' + id + ']').first();
                    if (labelElmt.length > 0) {
                        label = labelElmt.text();
                    }
                }
    
                this.reset = function () {
    
                    // unregister event handlers from previous section element,
                    // and detach it from the DOM
                    var prevSection = $(SECTION, container);
                    if (prevSection) {
                        prevSection.off('dragenter', useForm ? noOpDragAndDrop : onDragEnter);
                        prevSection.off('dragleave', useForm ? noOpDragAndDrop : onDragLeave);
                        prevSection.off('dragover', noOpDragAndDrop);
                        prevSection.off('drop', useForm ? noOpDragAndDrop : onDrop);
                        $(FILE_CHOOSE, container).off('change', changeHandler);
                        // detach the old template from the DOM
                        // do not remove because IE transport needs it 
                        $(TEMPLATE, container).detach();
                    }
                    
                    selectedFiles = null;
                    // install new section from the template
                    container.append(template.clone());

                    resetDropZoneMessage();
                    $(MESSAGE, container).show();
                    $(FILE_SIZE, container).empty();         
                    clearErrorMessage();
                    
                    // set the label for the file input element if the label
                    // exists. Otherwise, use the default. This is done
                    // mainly for FormStateView
                    setLabel(container.attr('id'));
                    if (label) {
                        $(LABEL, elem).text(label);
                    }
                    
                    clearFileInput();
    
                    // Install handlers for drop zone
                    $(SECTION, container).on('dragenter', useForm ? noOpDragAndDrop : onDragEnter);
                    $(SECTION, container).on('dragleave', useForm ? noOpDragAndDrop : onDragLeave);
                    $(SECTION, container).on('dragover', noOpDragAndDrop);
                    $(SECTION, container).on('drop', useForm ? noOpDragAndDrop : onDrop);
                    
                    // Install handlers for "Choose File" button:
                    $(FILE_CHOOSE, container).on('click', function() {
                        $(FILE_CHOOSE, container).removeAttr('dropped-file');
                    });
                    $(FILE_CHOOSE, container).on('change', changeHandler); 
                    showDisclaimerMessage();
                }

                /**
                 * 
                 */
                this.initialize = function (elem, options) {
                    container = $(elem);
                    if (options) {
                        selectedFiles = options.files;
                        onFileSelection = options.onFileSelection;
                        if (options.compactMode) {
                            $(container).addClass('hp-compact');
                        }
                    }
                    if (typeof FormData === 'undefined') {
                        // IE doesn't have FormData so we have to use the iframe transport in a form submit
                        useForm = true;
                    } else {
                        useForm = false;
                    }
                    template = $(environment.isKioskMode() ? kioskTemplate : rawTemplate);
                    localizer.localizeDom(template);
                }
            }

            if ( typeof options === 'string' ) { 
                // call method
                var args = Array.prototype.slice.call( arguments, 1 );

                this.each(function() {
                    instance = $.data( this, 'hpFileChooser' );
                    if ( !instance ) {
                        if (window.console) {
                            window.console.error(
                                "cannot call methods on hpFileChooser prior to initialization; " +
                                "attempted to call method '" + options + "'" );
                        }
                        return;
                    }
                    if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
                        if (window.console) {
                            window.console.error(
                                "no such method '" + options + "' for hpFileChooser instance" );
                        }
                        return;
                    }
                    instance[ options ].apply( instance, args );
                });  
            } else {
                // pluginify
                var ret;
                this.each(function() {
                    var $elem = $(this);
                    instance = new hpFileChooser($elem[0]);
                    $.data(this, 'hpFileChooser', instance);
                    instance.initialize($elem[0], options);
                    instance.reset();
                    ret = ret ? ret.add($elem) : $elem;
                });
                return ret;
            }
        };
    }(jQuery));
});