(function ($) {
    var admin = function () {
        return this.init();
    };

    //setting up csrf token
    $.ajaxSetup({
        headers: {
            'X-CSRF-TOKEN': window.csrf
        }
    });

    admin.prototype = {

        //properties

        /*
         * Main admin container
         *
         * @type jQuery object
         */
        $container: null,


        /*
         * KO viewModel
         */
        viewModel: {


            /* The settings name
             * string
             */
            settingsName: ko.observable(''),

            /* The settings title
             * string
             */
            settingsTitle: ko.observable(''),

            /* The model edit fields
             * array
             */
            editFields: ko.observableArray(),

            /* If this is set to true, the form becomes uneditable
             * bool
             */
            freezeForm: ko.observable(false),

            /* If this is set to true, the action buttons on the form cannot be accessed
             * bool
             */
            freezeActions: ko.observable(false),

            /* If custom actions are supplied, they are stored here
             * array
             */
            actions: ko.observableArray(),

            /* The languages array holds text for the current language
             * object
             */
            languages: {},

            /* The status message and the type ('', 'success', 'error')
             * strings
             */
            statusMessage: ko.observable(''),
            statusMessageType: ko.observable(''),

            /**
             * Saves the item with the current settings
             */
            save: function () {
                var self = this,
                    saveData = ko.mapping.toJS(self);

                saveData._token = csrf;

                self.statusMessage(self.languages['saving']).statusMessageType('');
                self.freezeForm(true);

                $.ajax({
                    url: save_url,
                    data: saveData,
                    dataType: 'json',
                    type: 'POST',
                    complete: function () {
                        self.freezeForm(false);
                    },
                    success: function (response) {
                        if (response.success) {
                            self.statusMessage(self.languages['saved']).statusMessageType('success');

                            //update the model
                            self.updateData(response.data);

                            //update the custom actions
                            self.actions(response.actions);
                        }
                        else
                            self.statusMessage(response.errors).statusMessageType('error');
                    }
                });
            },

            /**
             * Performs a custom action
             *
             * @param string    action
             * @param object    messages
             * @param string    confirmation
             */
            customAction: function (action, messages, confirmation) {
                var self = this;

                //if a confirmation string was supplied, flash it in a confirm()
                if (confirmation) {
                    if (!confirm(confirmation))
                        return false;
                }

                self.statusMessage(messages.active).statusMessageType('');
                self.freezeForm(true);

                $.ajax({
                    url: custom_action_url,
                    data: {_token: csrf, action_name: action},
                    dataType: 'json',
                    type: 'POST',
                    complete: function () {
                        self.freezeForm(false);
                    },
                    success: function (response) {
                        if (response.success) {
                            self.statusMessage(messages.success).statusMessageType('success');

                            //update the custom actions
                            self.actions(response.actions);

                            // if this is a redirect, redirect the user to the supplied url
                            if (response.redirect)
                                window.location.href = response.redirect;

                            //if there was a file download initiated, redirect the user to the file download address
                            if (response.download)
                                self.downloadFile(response.download);
                        }
                        else
                            self.statusMessage(response.error).statusMessageType('error');
                    }
                });
            },

            /**
             * Initiates a file download
             *
             * @param string    url
             */
            downloadFile: function (url) {
                var hiddenIFrameId = 'hiddenDownloader',
                    iframe = document.getElementById(hiddenIFrameId);

                if (iframe === null) {
                    iframe = document.createElement('iframe');
                    iframe.id = hiddenIFrameId;
                    iframe.style.display = 'none';
                    document.body.appendChild(iframe);
                }

                iframe.src = url;
            },

            /**
             * Updates the view model data
             *
             * @param array        data
             */
            updateData: function (data) {
                var self = this;

                //iterate over the data and find the associated observable
                $.each(data, function (i, el) {
                    self[i](el);
                });
            }

        },


        //methods

        /**
         * Init method
         */
        init: function () {
            //set up the basic pieces of data
            this.$container = $('#admin_content');

            var viewModel = ko.mapping.fromJS(adminData.data);

            $.extend(this.viewModel, viewModel);

            this.viewModel.settingsName(adminData.name);
            this.viewModel.settingsTitle(adminData.title);
            this.viewModel.actions(adminData.actions);
            this.viewModel.languages = adminData.languages;

            //now that we have most of our data, we can set up the computed values
            this.initComputed();

            //prepare the edit fields
            this.viewModel.editFields = this.prepareEditFields();

            //set up the KO bindings
            ko.applyBindings(this.viewModel, $('#main_content')[0]);

            //set up the subscriptions
            this.initSubscriptions();

            //set up the events
            this.initEvents();

            return this;
        },

        /**
         * Prepare the edit fields
         *
         * @return object with loadingOptions observables
         */
        prepareEditFields: function () {
            var self = this,
                fields = [];

            $.each(adminData.edit_fields, function (ind, field) {
                //if this is an image field, set the upload params
                if (field.type === 'image' || field.type === 'file') {
                    field.uploading = ko.observable(false);
                    field.upload_percentage = ko.observable(0);
                }

                //add the id field
                field.field_id = 'edit_field_' + ind;

                fields.push(field);
            });

            return fields;
        },

        /**
         * Inits the KO subscriptions
         */
        initSubscriptions: function () {
            var self = this;

        },

        /**
         * Inits the page events
         */
        initEvents: function () {
            var self = this;

        },

        /**
         * Initializes the computed observables
         */
        initComputed: function () {

        },

        /**
         * Handles a window resize
         */
        resizePage: function () {

        }
    };


    //set up the admin instance
    $(function () {
        if ($('#settings_page').length)
            window.admin = new admin();
    });
})(jQuery);