angular.module('customUploader')

// plupload object
// .factory('plupload', ['$window', function ($window) {
//
//                return ($window.plupload);
//}])


.directive('uploaderDirective',['$timeout','plupload', '$','_', function($timeout, plupload, $,_) {
    // randomString
    function randomString(len, charSet) {
        charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        var randomString = '';
        for (var i = 0; i < len; i++) {
            var randomPoz = Math.floor(Math.random() * charSet.length);
            randomString += charSet.substring(randomPoz, randomPoz + 1);
        }
        return randomString;
    }

    return {
        restrict: "AE",
        templateUrl: 'js/common/directives/uploader/upload_directive_tmpl.html',
        //transclude: true,
        scope: {
            // Option setting
            urlUpload:"@url",
            label:"@label",
            bttext:"@bttext",
            filelist:"=filelist",
            dragAndDropContainer:"@container",
            maxfilesize:"=maxfilesize",
            // File extension allow upload
            extension:"@extension"
            // 
        },
        
       link:function (scope, element, attrs) {
       // Max file size upload
        var MAX_FILE_SIZE = scope.maxfilesize; 
        // URL Upload
        var url_api_upload=scope.urlUpload;
        
        // Create uploader
        var uploader ={};
        
        scope.btUploadId=randomString(5);
        
        // I provide access to the file list inside of the directive. This can be 
        // used to render the items being uploaded.
        scope.queue = [] || uploader.files; //new PublicQueue();

        // Create info object contains some information about upload files
        scope.uploading = false, scope.info = { current_file: {}, total: 0, uploaded: 0 };
        
        // Remove file from queue uploading
        // @param {object} file
        scope.cancelFile = function(file) {

            var ids = [];

            // Update status in queue
            _.forEach( uploader.files, function( f ) {

                if ( f.id == file.id ) {
                    f.status = 6;
                    f.loaded = 0;
                    f.percent = 0;

                    ids.push( f.id );
                }
            });

            doCancelUpload( ids );

            // Stop
            uploader.stop();

            var files = _.filter( uploader.files, function( f ) {
                
                return f.status == plupload.QUEUED && f.id != file.id;
            });

            // Start new file
            if ( files.length > 0 ) {

                uploader.start();
            }
        };

        // Re-try upload file
        // @param {object} file
        scope.retry = function(file) {
            _.forEach( uploader.files, function( f ) {
                if ( f.id == file.id )
                    f.status = plupload.QUEUED;
            });

            var files = _.filter( uploader.files, {status: plupload.QUEUED} );
            if ( files.length > 0 && isNotUploading() ) {
                uploader.start();
            }
        };
        // Cancel all file
        scope.cancelAll = function() {

            if ( isUploading() ) {

                uploader.stop();
            }

            var ids = [];

            _.forEach( uploader.files, function( f ) {

                // Cancel when uploading or in queue
                if (f.status == plupload.UPLOADING || f.status == plupload.QUEUED) {

                    f.loaded = 0;
                    f.percent = 0;
                    f.status = 6;
                    // Push to list
                    ids.push( f.id );
                }
            });

            doCancelUpload( ids );
        };
        // Clean-up upload
        scope.cleanUp = function () {

            // Remove all
            if ( uploader ) {

                if ( isNotUploading() ) {
                    // Clean up
                    uploader.splice( 0 );
                    // Clean queue as well
                    scope.queue = [];
                }
                else {

                    scope.cancelAll();
                }
            }
            
            // Hide modal
            element.find('#modal-upload').addClass('hid');
        };
        // Minimize upload modal
        scope.minimize = function () {
            // Hide modal
            var m = element.find('#modal-upload');
            m.toggleClass('minimize');
        };
        // Check window & container size
        var $percentDOM = element.find('#current-percent');
        // Handle resize window
        window.addEventListener('resize', function(){
            // Refresh uploader
            uploader.refresh();
        });
        
        // Do cancel upload file
        function doCancelUpload(ids) {
            if (ids.length === 0)
                return;
            // TODO 
            // call API to request cancel
        }
        // Handle before call upload
        function handleBeforeUpload( uploader, file) {
            // Set params
            scope.info.current_file = file;
            uploader.settings.multipart_params.file_name=file.name;
        }
        // Handle error
        function handleError(uploader, error ) {

            // We have to call cancel file
            // Get file error
            var f = error.file;
            if ( f ) {
                if ( error.code === plupload.HTTP_ERROR ) {
                    // Check valid
                    // Notify that this file is error
                    doCancelUpload( [ f.id ] );
                }
                // Show error
                showUploadError( f, error.code);
            }
        }

        // Hanlde file added
        function handleFilesAdded(uploader, files) {
            // Get modal
            var modal = element.find('#modal-upload');
            // Remove minimize class
            modal.removeClass( 'minimize' );
            if ( modal.hasClass( 'hid' ) )
                modal.removeClass( 'hid' ).css('display', 'none').slideDown('slow'); 
            // Animiation
            for (var i in files) {
                scope.queue.push(files[i]);
            }
            var total = uploader.files.length + files.length;
            // Set as total files
            scope.info.total = total;
            // Tell AngularJS that something has changed (the public queue will have 
            // been updated at this point).
            scope.$apply();
        }

        //  Handle file uploaded 
        function handleFileUploaded( uploader, file, response ) {
            scope.$apply(
                function() {
                    var result = angular.fromJson(response.response );
//                    if (result.result === 'SUCCESS') {
//                        scope.info.uploaded = _.filter( uploader.files , function ( f ) {
//                            return f.status === plupload.DONE;
//                        }).length;
//                        // Notify the response from the server.
//                        scope.$emit('UploadCompleted', result);
//                        console.log('Upload success');
//                    } else {
//                          alert('Upload error');
//                    }
                }
            );         
        }

        // Handle process changed
        function handleUploadProgress( uploader, file ) {
            if (isUploading()) {
                scope.$apply( function() {                   
                    $percentDOM.removeClass('hid').text(file.percent + '%');
                    scope.$emit('UploadProgress',file.percent);
                });
            }
        }

        // Handle queue changed
        function handleQueueChanged(uploader) {
            
            // Find queue
            var files = _.filter(uploader.files, {status: plupload.QUEUED});

            if ( files.length && isNotUploading() ) {

                uploader.start();
            }
            
            // Safe apply
            $timeout( function () {
                
                scope.$apply();
            });
        }

        // Handle uploader's status changed
        function handleStateChanged( uploader ) {
            var check = isUploading();
            if ( check ) {
                element.addClass("uploading");
            } else {
                element.removeClass("uploading");
            }
            
            // Safe apply
            $timeout( function() {          
                 scope.$apply( function () {
                    scope.uploading = check;
                    if ( isUploading() ) {
                        $percentDOM.removeClass( 'hid' );
                    }
                    else {

                        $percentDOM.addClass( 'hid' );
                    }
                });
            });
        }

        // CHeck whether uploader is not uploading
        function isNotUploading() {

            return ( uploader.state === plupload.STOPPED );
        }

        // Check whether is uploading
        function isUploading() {
            
            if ( uploader )
                return(uploader.state === plupload.STARTED);
            else
                return false;
        }

        function showUploadError(file, errorCode) {
           // Handle upload error here
           alert("upload error" + errorCode);
        }
        
        // Initialize Directive
        function inititalize() {
            $timeout(function () {
                // Init plupload
                console.log("uploader.init...");
                uploader = new plupload.Uploader({
                    // Init Option setting for plUpload
                    // Document http://www.plupload.com/docs/v2/Options
                    runtimes: "html5,gears,browserplus,flash,html4",
                    // Upload the image to the API.
                    url: url_api_upload,
                    max_file_size: MAX_FILE_SIZE + 'mb',
                    chunk_size: '1024kb',
                    autostart: true,
                    unique_names: true,
                    filters: [
                        {title: 'Allow Files', extensions: scope.extension}
                    ],
                    // Set the name of file field (that contains the upload).
                    file_data_name: "file",
                    // The container, into which to inject the Input shim.
                    container: scope.dragAndDropContainer,
                    // The ID of the drop-zone element.
                    drop_element: scope.dragAndDropContainer,
                    // To enable click-to-select-files, you can provide a browse button. 
                    // We can use the same one as the drop zone.
                    browse_button: scope.btUploadId,
                    // Flash source
                    flash_swf_url: 'libs/plupload/plupload.flash.swf',
                    // We don't have any parameters yet; but, let's create the object now
                    // so that we can simply consume it later in the BeforeUpload event.
                    multipart_params: {
                        'Content-Type': 'multipart/form-data'
                    },
                    // Authen token
                    headers:{
                         'token':'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZGllbmNlIjoid2ViIiwiY3JlYXRlZCI6MTQ4OTMzNjYxODI5OSwiZXhwIjoxNDg5MzQwMjE4fQ.IBfS77x3SFP0uv6oFUlYbWq78CTzV1G2nBOu3_M-Jtu1ecRtqN2weBwDRZsXvZeq8vI-bWOewuW1KeAdhyl76g'
                    }
                    
                });

                // Initialize the plupload runtime.
                uploader.bind("Error", handleError);
                uploader.bind("FilesAdded", handleFilesAdded);
                uploader.bind("QueueChanged", handleQueueChanged);
                uploader.bind("BeforeUpload", handleBeforeUpload);
                uploader.bind("UploadProgress", handleUploadProgress);
                uploader.bind("FileUploaded", handleFileUploaded);
                uploader.bind("StateChanged", handleStateChanged);
                // Run init
                uploader.init();
            }, 1500);
        }

        // Destroy directive
        //
        scope.$on( "$destroy", function() {
            
            // Destroy uploader
            if ( uploader )
                uploader.destroy();
            
            // Unbind what i binded
            $('#container').unbind('dragenter dragleave drop');
            
            // Remove min height
            // $('#container')[0].style.minHeight = '';

           // win.off('resize', hanldeResize);
            
//            if (hintToast)
//                hintToast.closeCleanUp();

            // Clean up
            scope.queue = [];
        });
        
        scope.getThumnail = function (file) {
            if (file.icon)
                return file.icon;
            else
                return "images/doc-icon.png";
        };
        
        // Init
        inititalize();
    }
    };
}]);
