
var Fileman = Fileman || {};

kQuery(function($) {

    Fileman.ImageEditorFactory = {
        getEditor: function(type, options) {
            if (type === 'admin') {
                return new Fileman.ImageEditor.Admin(options);
            } else if (type === 'site') {
                return new Fileman.ImageEditor.Site(options);
            } else {
                return new Fileman.ImageEditor(options);
            }
        }
    };

    Fileman.ImageEditor = Koowa.Class.extend({
        loadedFile: {},
        getOptions: function() {
            return {
                site: null,
                baseurl: null,
                editorUrl: 'https://connect.joomlatools.com/image-editor/',
                fileUrl: '?option=com_fileman&view=file&connect=1&image=1',
                connectToken: null,

                onBeforeInitialize: function (instance) {
                },
                onAfterInitialize: function () {
                },
                onSaveImage: function (data, response) {
                    console.log(data, response);
                },
            }
        },

        initialize: function(options) {
            this.supr();

            this.setOptions(options);

            if (!this.options.baseurl) {
                this.options.baseurl = this.options.site+'/'+this.options.fileUrl;
            }

            if (this.options.onBeforeInitialize) {
                this.options.onBeforeInitialize.call(this, this);
            }

            this.attachEvents();

            if (this.options.onAfterInitialize) {
                this.options.onAfterInitialize(this);
            }
        },
        closeModal: function() {
            if (typeof $.magnificPopup !== 'undefined' && $.magnificPopup.instance) {
                $.magnificPopup.close();
            }
        },
        openModal: function() {
            var editorUrl = this.options.editorUrl;

            $.magnificPopup.open({
                items: {
                    src: editorUrl,
                    type: 'iframe'
                },
                closeOnBgClick: false,
                mainClass: 'koowa_dialog_modal'
            });
        },
        checkOrigin: function(origin) {
            return origin.match(/^https:\/\/(.*?)\.joomlatools.(?:com|xyz)$/);
        },
        saveImage: function(data) {
            var self = this;

            return new Promise(function(resolve, reject) {
                try {
                    var formdata = new FormData();
                    formdata.append("file", data.blob);
                    formdata.append("path", data.context.path);

                    var xhr = new XMLHttpRequest();
                    xhr.open('POST', self.options.baseurl+'&token='+data.context.token, true);
                    xhr.onerror = function() {reject("Network error.")};
                    xhr.onload = function() {
                        if (xhr.status === 200) {
                            self.options.onSaveImage(data, JSON.parse(xhr.response));
                            resolve(xhr.response);
                        }
                        else {
                            reject("Loading error:" + xhr.statusText)
                        }
                    };
                    xhr.send(formdata);
                }
                catch(err) {reject(err.message)}
            });
        },
        loadImage: function(path) {
            var self = this;

            var readyHandler = function(event) {
                console.log(event);
                if (self.checkOrigin(event.origin)) {
                    if (event.data.operation === 'ready') {
                        var image_url = self.options.baseurl+'&path='+path+'&token='+self.options.connectToken;

                        self.loadedFile = {
                            path: path,
                            token: self.options.connectToken,
                            site: self.options.site
                        };

                        self.convertImageToBlob(image_url).then(function(blob) {
                            document.querySelector('.mfp-iframe').contentWindow.postMessage({
                                operation: 'load',
                                //url: image_url,
                                blob: blob,
                                context: self.loadedFile
                            }, '*');

                            window.removeEventListener('message', readyHandler);
                        });

                    }
                }
            };

            window.addEventListener("message", readyHandler);

            this.closeModal();
            this.openModal();
        },

        convertImageToBlob: function(url) {
            return new Promise(function(resolve, reject) {
                try {
                    var xhr = new XMLHttpRequest();
                    xhr.open("GET", url);
                    xhr.responseType = "blob";
                    xhr.onerror = function() {reject("Network error.")};
                    xhr.onload = function() {
                        if (xhr.status === 200) {resolve(xhr.response)}
                        else {reject("Loading error:" + xhr.statusText)}
                    };
                    xhr.send();
                }
                catch(err) {reject(err.message)}
            });
        },

        attachEvents: function() {
            var self = this;

            window.addEventListener("message", function(event) {
                if (self.checkOrigin(event.origin)) {
                    if (event.data.operation === 'save') {
                        if (self.loadedFile && event.data.context && self.loadedFile.path === event.data.context.path) {
                            self.closeModal();

                            self.saveImage(event.data);
                        }
                    }
                }
            }, false);
        },

        encodeFilename: function(value) {
            value = encodeURI(value);

            var replacements = {'\\?': '%3F', '#': '%23'};

            for(var key in replacements)
            {   var regexp = new RegExp(key, 'g');
                value = value.replace(regexp, replacements[key]);
            }

            return value;
        },
        decodeFilename: function(value) {
            value = decodeURI(value);

            var replacements = {'%3F': '\\?', '%23': '#'};

            for(var key in replacements)
            {   var regexp = new RegExp(key, 'g');
                value = value.replace(regexp, replacements[key]);
            }

            return value;
        },
        forceReloadImage: function (src) {
            if (src instanceof $) {
                src = src.attr('src');
            }
            else if (src instanceof HTMLElement) {
                src = src.getAttribute('src');
            }

            function restoreImages(srcUrl, imgList) {
                for (var i = 0; i < imgList.length; i++) {
                    imgList[i].src = srcUrl;
                }
            }
            function prepareImagesForReload(srcUrl) {
                var result = $("img[src='" + srcUrl + "']").get();

                for (var i = 0; i < result.length; i++) {
                    /*
                    * Set the image to a reloading image, in this case an animated "reloading" svg
                    * Ideally this wont be displayed long enough to matter.
                        */
                    result[i].src = "data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid' class='uil-reload'%3E%3Cpath fill='none' class='bk' d='M0 0h100v100H0z'/%3E%3Cg%3E%3Cpath d='M50 15a35 35 0 1 0 24.787 10.213' fill='none' stroke='%23777' stroke-width='12'/%3E%3Cpath d='M50 0v30l16-15L50 0' fill='%23777'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 50 50' to='360 50 50' dur='1s' repeatCount='indefinite'/%3E%3C/g%3E%3C/svg%3E";
                }

                return result;
            }

            return new Promise(function(resolve, reject) {
                var imgList;
                var step = 0;
                var iframe = window.document.createElement("iframe");   // Hidden iframe, in which to perform the load+reload.

                /* Callback function, called after iframe load+reload completes (or fails).
                    Will be called TWICE unless twostage-mode process is cancelled. (Once after load, once after reload). */
                var iframeLoadCallback = function(e) {

                    if (step === 0) {
                        // initial load just completed.  Note that it doesn't actually matter if this load succeeded or not.

                        step = 1;
                        imgList = prepareImagesForReload(src);
                        iframe.contentWindow.location.reload(true); // initiate forced-reload!


                    } else if (step === 1) {
                        // forced re-load is done

                        restoreImages(src, imgList);
                        if (iframe.parentNode) iframe.parentNode.removeChild(iframe);

                        if ((e||window.event).type==="error") {
                            reject(e);
                        } else {
                            resolve(e);
                        }

                    }
                };

                iframe.style.display = "none";
                window.parent.document.body.appendChild(iframe); /* NOTE: if this is done AFTER setting src, Firefox MAY fail to fire the load event! */
                iframe.addEventListener("load",  iframeLoadCallback, false);
                iframe.addEventListener("error", iframeLoadCallback, false);
                iframe.src = src;
            });

        }
    });

    Fileman.ImageEditor.Admin = Fileman.ImageEditor.extend({
        getOptions: function() {
            var self = this;

            return $.extend(true, {}, this.supr(), {
                hasConnectSupport: false,
                toolbarButton: '.k-js-edit-image',
                connectErrorMessage: 'Image editor is available with Joomlatools Connect',
                onSaveImage: function(result) {
                    console.log(result);
                    if (result.blob && result.context && result.context.path) {
                        var parts = result.context.path.split('://');

                        if (parts.length === 2) {
                            var file = Object.values(Files.app.grid.nodes.filter(function(row) {
                                return row.container === parts[0] && row.filepath === self.decodeFilename(parts[1]);
                            }));

                            if (file.length === 1) {
                                // currentSrc is set to the thumbnail path
                                var currentSrc = file[0].element.getElement('.image-thumbnail').src;

                                // set saved image as src
                                file[0].element.getElement('.image-thumbnail').src = URL.createObjectURL(result.blob);

                                // force-reload thumbnail for next refresh
                                self.forceReloadImage(currentSrc);
                            }
                        }
                    }
                }
            });
        },

        attachEvents: function() {
            this.supr();

            this.toolbarButton = $(this.options.toolbarButton);

            if (!this.options.hasConnectSupport) {
                this.toolbarButton.ktooltip({
                    placement: 'bottom',
                    container:".k-ui-container",
                    delay:{"show":100,"hide":50},
                    title: Koowa.translate(this.options.connectErrorMessage)
                });
            }
            else {
                var self = this;

                var refreshButtons = function() {
                    var checked = Object.values(Files.app.grid.nodes.filter(function(row) { return row.checked }));

                    if (checked.length === 1 && checked[0].type === 'image') {
                        self.toolbarButton.filter('.k-is-supported').removeClass('k-is-disabled');
                    } else {
                        self.toolbarButton.filter('.k-is-supported').addClass('k-is-disabled');
                    }
                };

                var interval = setInterval(function () {
                    if (typeof Files.app === 'undefined') {
                        return;
                    }

                    clearInterval(interval);

                    Files.app.grid.addEvent('afterCheckNode', refreshButtons);
                    Files.app.grid.addEvent('afterDeleteNode', refreshButtons);
                    Files.app.grid.addEvent('afterReset', refreshButtons);
                    Files.app.grid.addEvent('afterMoveNodes', refreshButtons);

                    refreshButtons();
                }, 100);

                this.toolbarButton.addClass('k-is-supported').click(function(e) {
                    e.preventDefault();

                    var checked = Object.values(Files.app.grid.nodes.filter(function(row) { return row.checked }));

                    if (checked.length === 1 && checked[0].type === 'image') {
                        self.loadImage(checked[0].container+'://'+self.encodeFilename(checked[0].filepath));
                    }
                });
            }
        }
    });

    Fileman.ImageEditor.Site = Fileman.ImageEditor.extend({
        getOptions: function() {
            var self = this;

            return $.extend(true, {}, this.supr(), {
                hasConnectSupport: false,
                editButton: '.k-js-edit-image',
                connectErrorMessage: 'Image editor is available with Joomlatools Connect',
                onSaveImage: function(result, xhr) {
                    var entity = xhr.entity;

                    if (entity && entity.path) {
                        var image = document.querySelector('img.k-js-image-preview[data-path="'+entity.path+'"]');

                        if (image) {
                            // currentSrc is set to the thumbnail path
                            var currentSrc = image.src;

                            // set saved image as src
                            image.src = URL.createObjectURL(result.blob);

                            // force-reload thumbnail for next refresh
                            self.forceReloadImage(currentSrc);
                        }
                    }
                }
            });
        },

        attachEvents: function() {
            this.supr();

            var self = this;

            this.editButton = $(this.options.editButton);

            if (!this.options.hasConnectSupport) {
                this.editButton.hide();
                /*this.editButton.each(function(i, el) {
                    $(el).ktooltip({
                        placement: 'top',
                        delay:{"show":100,"hide":50},
                        title: Koowa.translate(self.options.connectErrorMessage)
                    });
                });*/
            }
            else {

                $(document.body).on('click', this.options.editButton, function(e) {
                    e.preventDefault();

                    var target = $(e.target).is(self.options.editButton) ? $(e.target) : $(e.target).parents(self.options.editButton);

                    var path = target.data('path');

                    if (path) {
                        self.loadImage(path);
                    }
                });
            }
        }
    });
});
