/**
* Module that controls the Dataverse user settings. Includes Knockout view-model
* for syncing data.
*/

var ko = require('knockout');
require('knockout.punches');
ko.punches.enableAll();
var $ = require('jquery');
var Raven = require('raven-js');
var bootbox = require('bootbox');
require('js/osfToggleHeight');

var language = require('js/osfLanguage').Addons.dataverse;
var osfHelpers = require('js/osfHelpers');
var addonSettings = require('js/addonSettings');

var ExternalAccount = addonSettings.ExternalAccount;

var $modal = $('#dataverseInputCredentials');


function ViewModel(url) {
    var self = this;
    const otherString = 'Other (Please Specify)';

    self.properName = 'Dataverse';
    self.apiToken = ko.observable();
    self.urls = ko.observable({});
    self.hosts = ko.observableArray([]);
    self.selectedHost = ko.observable();    // Host specified in select element
    self.customHost = ko.observable();      // Host specified in input element
    // Whether the initial data has been loaded
    self.loaded = ko.observable(false);
    self.accounts = ko.observableArray();

    // Designated host, specified from select or input element
    self.host = ko.pureComputed(function() {
        return self.useCustomHost() ? self.customHost() : self.selectedHost();
    });
    // Hosts visible in select element. Includes presets and "Other" option
    self.visibleHosts = ko.pureComputed(function() {
        return self.hosts().concat([otherString]);
    });
    // Whether to use select element or input element for host designation
    self.useCustomHost = ko.pureComputed(function() {
        return self.selectedHost() === otherString;
    });
    self.showApiTokenInput = ko.pureComputed(function() {
        return Boolean(self.selectedHost());
    });
    self.tokenUrl = ko.pureComputed(function() {
       return self.host() ? 'https://' + self.host() + '/account/apitoken' : null;
    });

    // Flashed messages
    self.message = ko.observable('');
    self.messageClass = ko.observable('text-info');

    /** Reset all fields from Dataverse host selection modal */
    self.clearModal = function() {
        self.message('');
        self.messageClass('text-info');
        self.apiToken(null);
        self.selectedHost(null);
        self.customHost(null);
    };

    self.updateAccounts = function() {
        var url = self.urls().accounts;
        var request = $.get(url);
        request.done(function(data) {
            self.accounts($.map(data.accounts, function(account) {
                var externalAccount =  new ExternalAccount(account);
                externalAccount.dataverseHost = account.host;
                externalAccount.dataverseUrl = account.host_url;
                return externalAccount;
            }));
            $('#dataverse-header').osfToggleHeight({height: 140});
        });
        request.fail(function(xhr, status, error) {
            Raven.captureMessage('Error while updating addon account', {
                url: url,
                status: status,
                error: error
            });
        });
        return request;
    };

    /** Send POST request to authorize Dataverse */
    self.sendAuth = function() {
        // Selection should not be empty
        if( !self.selectedHost() ){
            self.changeMessage("Please select a Dataverse repository.", 'text-danger');
            return;
        }

        var url = self.urls().create;
        return osfHelpers.postJSON(
            url,
            ko.toJS({
                host: self.host,
                api_token: self.apiToken
            })
        ).done(function() {
            self.clearModal();
            $modal.modal('hide');
            self.updateAccounts();

        }).fail(function(xhr, textStatus, error) {
            var errorMessage = (xhr.status === 401) ? language.authInvalid : language.authError;
            self.changeMessage(errorMessage, 'text-danger');
            Raven.captureMessage('Could not authenticate with Dataverse', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
    };

    self.askDisconnect = function(account) {
        var self = this;
        bootbox.confirm({
            title: 'Disconnect Dataverse Account?',
            message: '<p class="overflow">' +
                'Are you sure you want to disconnect the Dataverse account on <strong>' +
                account.name + '</strong>? This will revoke access to Dataverse for all projects associated with this account.' +
                '</p>',
            callback: function (confirm) {
                if (confirm) {
                    self.disconnectAccount(account);
                }
            },
            buttons:{
                confirm:{
                    label:'Disconnect',
                    className:'btn-danger'
                }
            }
        });
    };

    self.disconnectAccount = function(account) {
        var self = this;
        var url = '/api/v1/oauth/accounts/' + account.id + '/';
        var request = $.ajax({
            url: url,
            type: 'DELETE'
        });
        request.done(function(data) {
            self.updateAccounts();
        });
        request.fail(function(xhr, status, error) {
            Raven.captureMessage('Error while removing addon authorization for ' + account.id, {
                url: url,
                status: status,
                error: error
            });
        });
        return request;
    };

    /** Change the flashed status message */
    self.changeMessage = function(text, css, timeout) {
        self.message(text);
        var cssClass = css || 'text-info';
        self.messageClass(cssClass);
        if (timeout) {
            // Reset message after timeout period
            setTimeout(function() {
                self.message('');
                self.messageClass('text-info');
            }, timeout);
        }
    };

    // Update observables with data from the server
    self.fetch = function() {
        $.ajax({
            url: url,
            type: 'GET',
            dataType: 'json'
        }).done(function (response) {
            var data = response.result;
            self.urls(data.urls);
            self.hosts(data.hosts);
            self.loaded(true);
            self.updateAccounts();
        }).fail(function (xhr, textStatus, error) {
            self.changeMessage(language.userSettingsError, 'text-danger');
            Raven.captureMessage('Could not GET Dataverse settings', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
    };

    self.selectionChanged = function() {
        self.changeMessage('','');
    };

}

function DataverseUserConfig(selector, url) {
    // Initialization code
    var self = this;
    self.selector = selector;
    self.url = url;
    // On success, instantiate and bind the ViewModel
    self.viewModel = new ViewModel(url);
    osfHelpers.applyBindings(self.viewModel, self.selector);
}

module.exports = {
    DataverseViewModel: ViewModel,
    DataverseUserConfig: DataverseUserConfig    // for backwards-compat
};
