/**
 * This model is used by admin/analyse_album.blade.php, to analyse all images.
 * @constructor
 */
function AnalyseAlbumViewModel() {
    this.el = '#analyse-album';

    this.data = {
        imagesFailed: [],
        imagesToAnalyse: [],
        imagesInProgress: [],
        imagesRecentlyCompleted: [],
        numberSuccessful: 0,
        numberFailed: 0
    };

    this.computed = {
        failedPercentage: function () {
            var result = 0;

            if (this.numberTotal > 0)
            {
                result = (this.numberFailed / this.numberTotal) * 100;
            }

            return result.toFixed(2) + '%';
        },
        isCompleted: function () {
            return this.numberTotal > 0 && (this.numberSuccessful + this.numberFailed >= this.numberTotal);
        },
        latestCompletedImages: function() {
            var startIndex = this.imagesRecentlyCompleted.length - 3 < 0
                ? 0
                : this.imagesRecentlyCompleted.length - 3;
            var endIndex = startIndex + 3;

            return this.imagesRecentlyCompleted.slice(startIndex, endIndex);
        },
        numberTotal: function () {
            return this.imagesToAnalyse.length;
        },
        successfulPercentage: function () {
            var result = 0;

            if (this.numberTotal > 0)
            {
                result = (this.numberSuccessful / this.numberTotal) * 100;
            }

            return result.toFixed(2) + '%';
        }
    };

    this.methods = {
        // This method is called when an image is added to the array, automatically issue it for analysis
        // item is an instance of AnalyseImageViewModel
        analyseImage: function (item) {
            var self = this;
            this.imagesToAnalyse.push(item);

            $.ajax(
                item.url,
                {
                    beforeSend: function() {
                        self.imagesInProgress.push(item);
                    },
                    dataType: 'json',
                    error: function (xhr, textStatus, errorThrown) {
                        self.numberFailed++;
                        self.imagesFailed.push({
                            'name': item.name,
                            'reason': textStatus
                        });
                        item.isSuccessful = false;
                        item.isPending = false;
                    },
                    method: 'POST',
                    success: function (data) {
                        if (data.is_successful) {
                            self.numberSuccessful++;
                            item.isSuccessful = true;
                            item.isPending = false;

                            // Push into our "recently completed" array
                            self.imagesRecentlyCompleted.push(item);
                            var indexToRemove = self.imagesInProgress.indexOf(item);
                            if (indexToRemove > -1)
                            {
                                self.imagesInProgress.splice(indexToRemove, 1);
                            }

                            // Remove it again after a few seconds
                            /*window.setTimeout(function() {
                                var indexToRemove = self.imagesRecentlyCompleted.indexOf(item);
                                if (indexToRemove > -1) {
                                    self.imagesRecentlyCompleted.splice(indexToRemove, 1);
                                }
                            }, 2000);*/
                        }
                        else {
                            self.numberFailed++;
                            self.imagesFailed.push({
                                'name': item.name,
                                'reason': data.message
                            });
                            item.isSuccessful = false;
                            item.isPending = false;
                        }
                    }
                }
            );
        }
    };
}

/**
 * This model is used by admin/analyse_album.blade.php, as a sub-model of AnalyseAlbumViewModel.
 * @param image_info Array of information about the image
 * @constructor
 */
function AnalyseImageViewModel(image_info) {
    this.isPending = true;
    this.isSuccessful = false;
    this.name = image_info.name;
    this.photoID = image_info.photo_id;
    this.url = image_info.url;
}

/**
 * This model is used by admin/show_album.blade.php to handle photo changes.
 * @param album_id ID of the album the photos are in
 * @param language Array containing language strings
 * @param urls Array containing URLs
 * @constructor
 */
function EditPhotosViewModel(album_id, language, urls) {
    this.el = '#photos-tab';

    this.data = {
        albums: [],
        bulkModifyMethod: '',
        isSubmitting: false,
        photoIDs: [],
        photoIDsAvailable: [],
        selectAllInAlbum: 0
    };

    // When a photo is un-selected, remove the "select all in album" flag as the user has overridden the selection
    /*self.photoIDs.subscribe(function (changes)
    {
        if (changes[0].status !== 'deleted')
        {
            return;
        }

        self.selectAllInAlbum(0);
    }, null, 'arrayChange');*/

    this.methods = {
        // Called when the Apply button on the "bulk apply selected actions" form is clicked
        bulkModifySelected: function (e) {
            if (this.isSubmitting) {
                return true;
            }

            var self = this;
            var bulk_form = $(e.target).closest('form');

            if (this.bulkModifyMethod === 'change_album') {
                // Prompt for the new album to move to
                this.promptForNewAlbum(function (dialog) {
                    var album_id = $('select', dialog).val();
                    $('input[name="new-album-id"]', bulk_form).val(album_id);

                    self.isSubmitting = true;
                    $('button[name="bulk-apply"]', bulk_form).click();
                    _bt_showLoadingModal();
                });

                e.preventDefault();
                return false;
            }
            else if (this.bulkModifyMethod === 'delete') {
                // Prompt for a confirmation - are you sure?!
                bootbox.dialog({
                    message: language.delete_bulk_confirm_message,
                    title: language.delete_bulk_confirm_title,
                    buttons: {
                        cancel: {
                            label: language.action_cancel,
                            className: "btn-secondary"
                        },
                        confirm: {
                            label: language.action_delete,
                            className: "btn-danger",
                            callback: function () {
                                self.isSubmitting = true;
                                $('button[name="bulk-apply"]', bulk_form).click();
                                _bt_showLoadingModal();
                            }
                        }
                    }
                });

                e.preventDefault();
                return false;
            }

            // All other methods submit the form as normal
            return true;
        },
        changeAlbum: function (e) {
            this.selectPhotoSingle(e.target);

            var photo_id = this.photoIDs[0];
            this.photoIDs = [];

            this.promptForNewAlbum(function (dialog) {
                var album_id = $('select', dialog).val();
                $.post(urls.move_photo.replace(/\/0$/, '/' + photo_id), {'new_album_id': album_id}, function () {
                    window.location.reload();
                });
                //_bt_showLoadingModal();
            });

            e.preventDefault();
            return false;
        },
        deletePhoto: function (e) {
            var self = this;
            this.selectPhotoSingle(e.target);

            var photo_id = self.photoIDs[0];
            this.photoIDs = [];

            bootbox.dialog({
                message: language.delete_confirm_message,
                title: language.delete_confirm_title,
                buttons: {
                    cancel: {
                        label: language.action_cancel,
                        className: "btn-secondary"
                    },
                    confirm: {
                        label: language.action_delete,
                        className: "btn-danger",
                        callback: function () {
                            var url = urls.delete_photo;
                            url = url.replace(/\/0$/, '/' + photo_id);

                            $('.loading', parent).show();

                            $.post(url, {'_method': 'DELETE'}, function (data) {
                                window.location.reload();
                            });
                        }
                    }
                }
            });

            e.preventDefault();
            return false;
        },
        flip: function (horizontal, vertical, parent) {
            var url = urls.flip_photo;
            url = url.replace('/0/', '/' + this.photoIDs[0] + '/');

            if (horizontal) {
                url = url.replace(/\/-1\//, '/1/');
            }
            else {
                url = url.replace(/\/-1\//, '/0/');
            }

            if (vertical) {
                url = url.replace(/\/-2$/, '/1');
            }
            else {
                url = url.replace(/\/-2$/, '/0');
            }

            $('.loading', parent).show();
            $.post(url, function () {
                var image = $('img.photo-thumbnail', parent);
                var originalUrl = image.data('original-src');
                image.attr('src', originalUrl + "&_=" + new Date().getTime());

                $('.loading', parent).hide();
            });

            this.photoIDs = [];
        },
        flipBoth: function (e) {
            this.selectPhotoSingle(e.target);
            this.flip(true, true, $(e.target).closest('.photo'));

            e.preventDefault();
            return false;
        },
        flipHorizontal: function (e) {
            this.selectPhotoSingle(e.target);
            this.flip(true, false, $(e.target).closest('.photo'));

            e.preventDefault();
            return false;
        },
        flipVertical: function (e) {
            this.selectPhotoSingle(e.target);
            this.flip(false, true, $(e.target).closest('.photo'));

            e.preventDefault();
            return false;
        },
        isPhotoSelected: function(photoID) {
            if (this.photoIDs.indexOf(photoID) > -1)
            {
                return 'checked';
            }

            return '';
        },
        promptForNewAlbum: function (callback_on_selected) {
            var albums = this.albums;
            var select = $('<select/>')
                .attr('name', 'album_id')
                .addClass('form-control');

            for (var i = 0; i < albums.length; i++) {
                var option = $('<option/>')
                    .attr('value', albums[i].id)
                    .html(albums[i].name)
                    .appendTo(select);

                // Pre-select the current album
                if (album_id === albums[i].id) {
                    option.attr('selected', 'selected');
                }
            }

            bootbox.dialog({
                message: $('<p/>').html(language.change_album_message).prop('outerHTML') + select.prop('outerHTML'),
                title: language.change_album_title,
                buttons: {
                    cancel: {
                        label: language.action_cancel,
                        className: 'btn-secondary'
                    },
                    confirm: {
                        label: language.action_continue,
                        className: 'btn-success',
                        callback: function () {
                            callback_on_selected(this);
                        }
                    }
                }
            });
        },
        regenerateThumbnails: function (e) {
            this.selectPhotoSingle(e.target);
            var parent = $(e.target).closest('.photo');

            var url = urls.regenerate_thumbnails;
            url = url.replace(/\/0$/, '/' + this.photoIDs[0]);

            $('.loading', parent).show();
            $.post(url, function () {
                var image = $('img.photo-thumbnail', parent);
                var originalUrl = image.data('original-src');
                image.attr('src', originalUrl + "&_=" + new Date().getTime());

                $('.loading', parent).hide();
            });

            this.photoIDs = [];

            e.preventDefault();
            return false;
        },
        replacePhoto: function (e) {
            var self = this;

            this.selectPhotoSingle(e.target);
            var parent = $(e.target).closest('.photo');

            bootbox.dialog({
                message: $('<p/>').html(language.replace_image_message).prop('outerHTML') +
                    $('#replace-image-form').clone().removeAttr('style').attr('id', 'replace-image-form-visible').prop('outerHTML'),
                title: language.replace_image_title,
                buttons: {
                    cancel: {
                        label: language.action_cancel,
                        className: 'btn-secondary'
                    },
                    confirm: {
                        label: language.action_continue,
                        className: 'btn-success',
                        callback: function () {
                            $('input[name="photo_id"]', '#replace-image-form-visible').val(self.photoIDs[0]);
                            $('#replace-image-form-visible').submit();
                        }
                    }
                }
            });

            e.preventDefault();
            return false;
        },
        rotate: function (angle, parent) {
            var url = urls.rotate_photo;
            url = url.replace('/0/', '/' + this.photoIDs[0] + '/');
            url = url.replace(/\/1$/, '/' + angle);

            $('.loading', parent).show();
            $.post(url, function () {
                var image = $('img.photo-thumbnail', parent);
                var originalUrl = image.data('original-src');
                image.attr('src', originalUrl + "&_=" + new Date().getTime());

                $('.loading', parent).hide();
            });

            this.photoIDs = [];
        },
        rotateLeft: function (e) {
            this.selectPhotoSingle(e.target);
            this.rotate(90, $(e.target).closest('.photo'));

            e.preventDefault();
            return false;
        },
        rotateRight: function(e)
        {
            this.selectPhotoSingle(e.target);
            this.rotate(270, $(e.target).closest('.photo'));

            e.preventDefault();
            return false;
        },
        selectAll: function() {
            var self = this;
            bootbox.dialog({
                title: language.select_all_choice_title,
                message: language.select_all_choice_message,
                buttons: {
                    select_all: {
                        label: language.select_all_choice_all_action,
                        className: 'btn-secondary',
                        callback: function()
                        {
                            self.selectAllInAlbum = 1;
                            for (i = 0; i < self.photoIDsAvailable.length; i++)
                            {
                                self.photoIDs.push(self.photoIDsAvailable[i]);
                            }
                        }
                    },
                    select_visible: {
                        label: language.select_all_choice_visible_action,
                        className: 'btn-primary',
                        callback: function()
                        {
                            self.selectAllInAlbum = 0;
                            for (i = 0; i < self.photoIDsAvailable.length; i++)
                            {
                                self.photoIDs.push(self.photoIDsAvailable[i]);
                            }
                        }
                    }
                }
            });

            return false;
        },
        selectNone: function() {
            this.photoIDs = [];
            this.selectAllInAlbum = 0;

            return false;
        },
        selectPhotoSingle: function (link_item) {
            // Get the photo ID from the clicked link
            var parent = $(link_item).closest('.photo');
            var photo_id = $(parent).data('photo-id');

            // Save the photo ID
            this.photoIDs = [];
            this.photoIDs.push(photo_id);
        },
        switchToUploadTab: function (e) {
            $('.nav-tabs a[href="#upload-tab"]').tab('show');

            e.preventDefault();
            return false;
        }
    }
}

function SlideShowViewModel(required_timeout_ms) {
    this.el = '#slideshow-container';

    this.data = {
        current: null,
        currentIndex: 0,
        images: [],
        interval: null,
        isPaused: false,
        isRunning: false
    };

    this.methods = {
        changeCurrentImage: function(photo_id)
        {
            for (var i = 0; i < this.images.length; i++)
            {
                var this_image = this.images[i];
                if (this_image.id === photo_id)
                {
                    this.current = this_image;
                    this.currentIndex = i;
                    window.clearInterval(this.interval);
                    this.interval = window.setInterval(this.rotateNextImage, required_timeout_ms);
                    return;
                }
            }
        },
        continueSlideshow: function() {
            this.isPaused = false;
            this.interval = window.setInterval(this.rotateNextImage, required_timeout_ms);
        },
        pauseSlideshow: function(e) {
            this.isPaused = true;
            window.clearInterval(this.interval);
        },
        rotateNextImage: function() {
            var next_index = this.currentIndex + 1;
            if (next_index >= this.images.length)
            {
                next_index = 0;
            }

            this.current = this.images[next_index];
            this.currentIndex = next_index;
        },
        startSlideshow: function() {
            if (this.images.length <= 0)
            {
                return;
            }

            this.interval = window.setInterval(this.rotateNextImage, required_timeout_ms);

            this.current = this.images[0];
            this.isRunning = true;
        }
    };
}

/**
 * This model is used by admin/show_album.blade.php to handle photo uploads.
 * @param album_id ID of the album the photos are being uploaded to
 * @param queue_token Unique token of the upload queue to save the photos to
 * @param language Array containing language strings
 * @param urls Array containing URLs
 * @constructor
 */
function UploadPhotosViewModel(album_id, queue_token, language, urls) {
    this.el = '#upload-tab';

    this.data = {
        currentStatus: '',
        imagesFailed: 0,
        imagesTotal: 0,
        imagesUploaded: 0,
        isBulkUploadInProgress: false,
        isUploadInProgress: false,
        statusMessages: []
    };

    this.computed = {
        failedPercentage: function () {
            var result = 0;

            if (this.imagesTotal > 0)
            {
                result = (this.imagesFailed / this.imagesTotal) * 100;
            }

            return result.toFixed(2) + '%';
        },
        successfulPercentage: function () {
            var result = 0;

            if (this.imagesTotal > 0)
            {
                result = (this.imagesUploaded / this.imagesTotal) * 100;
            }

            return result.toFixed(2) + '%';
        }
    };

    this.methods = {
        // This method is called when an image is uploaded - regardless if it fails or not
        onUploadCompleted: function () {
            this.currentStatus = language.upload_status
                .replace(':current', (this.imagesUploaded + this.imagesFailed))
                .replace(':total', this.imagesTotal);

            if ((this.imagesFailed + this.imagesUploaded) >= this.imagesTotal) {
                this.isUploadInProgress = false;

                if (this.imagesFailed === 0 && this.imagesUploaded > 0) {
                    window.location = urls.analyse;
                }
            }
        },
        // This method is called when an uploaded image fails
        onUploadFailed: function (data, file_name) {
            this.imagesFailed++;
            this.statusMessages.push({
                'message_class': 'text-danger',
                'message_text': language.image_failed.replace(':file_name', file_name)
            });
            this.onUploadCompleted();
        },
        // This method is called when an uploaded image succeeds
        onUploadSuccessful: function (data, file_name) {
            if (data.is_successful) {
                this.imagesUploaded++;
                // Don't add to statusMessages() array so user only sees errors
                /*self.statusMessages.push({
                 'message_class': 'text-success',
                 'message_text': language.image_uploaded.replace(':file_name', file_name)
                 });*/
                this.onUploadCompleted();
            }
            else {
                this.onUploadFailed(data, file_name);
            }
        },
        uploadFile: function uploadImageFile(formObject, imageFile) {
            var self = this;
            var formData = new FormData();
            formData.append('album_id', album_id);
            formData.append('queue_token', queue_token);
            formData.append('photo[]', imageFile, imageFile.name);

            $.ajax(
                {
                    contentType: false,
                    data: formData,
                    error: function (data) {
                        self.onUploadFailed(data, imageFile.name);
                    },
                    method: $(formObject).attr('method'),
                    processData: false,
                    success: function (data) {
                        self.onUploadSuccessful(data, imageFile.name);
                    },
                    url: $(formObject).attr('action')
                }
            );
            this.isUploadInProgress = true;

            this.currentStatus = language.upload_status
                .replace(':current', 0)
                .replace(':total', this.imagesTotal);
        },
        uploadBulkFiles: function(event) {
            this.isBulkUploadInProgress = true;
            return true;
        },
        uploadIndividualFiles: function(event) {
            var fileSelect = $('input[type=file]', event.target);

            // Get the selected files
            var files = fileSelect[0].files;

            if (files.length === 0)
            {
                alert(language.no_file_selected);
                event.preventDefault();
                return false;
            }

            // Reset statistics
            this.currentStatus = '';
            this.statusMessages = [];
            this.imagesUploaded = 0;
            this.imagesFailed = 0;
            this.imagesTotal = files.length;
            this.isUploadInProgress = true;

            // Loop through each of the selected files and upload them individually
            for (var i = 0; i < files.length; i++)
            {
                var file = files[i];

                // We're only interested in image files
                if (!file.type.match('image.*'))
                {
                    alert(language.not_an_image_file.replace(':file_name', file.name));
                    this.onUploadFailed(null, file.name);
                    continue;
                }

                // Upload the file
                this.uploadFile(event.target, file);
            }

            // Prevent standard form upload
            event.preventDefault();
            return false;
        }
    };
}