/*******************************************************************************
 * Copyright 2018 The MIT Internet Trust Consortium
 *
 * Portions copyright 2011-2013 The MITRE Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
var WhiteListModel = Backbone.Model.extend({

	idAttribute: "id",

	initialize: function() {
	},

	urlRoot: "api/whitelist"

});

var WhiteListCollection = Backbone.Collection.extend({
	initialize: function() {
		// this.fetch();
	},

	getByClientId: function(clientId) {
		var clients = this.where({
			clientId: clientId
		});
		if (clients.length == 1) {
			return clients[0];
		} else {
			return null;
		}
	},

	model: WhiteListModel,
	url: "api/whitelist"

});

var WhiteListListView = Backbone.View.extend({
	tagName: 'span',

	initialize: function(options) {
		this.options = options;
	},

	load: function(callback) {
		if (this.model.isFetched && this.options.clientList.isFetched && this.options.systemScopeList.isFetched) {
			callback();
			return;
		}

		$('#loadingbox').sheet('show');
		$('#loading').html('<span class="label" id="loading-whitelist">' + $.t('whitelist.whitelist') + '</span> ' + '<span class="label" id="loading-clients">' + $.t('common.clients') + '</span> ' + '<span class="label" id="loading-scopes">' + $.t('common.scopes') + '</span> ');

		$.when(this.model.fetchIfNeeded({
			success: function(e) {
				$('#loading-whitelist').addClass('label-success');
			},
			error: app.errorHandlerView.handleError()
		}), this.options.clientList.fetchIfNeeded({
			success: function(e) {
				$('#loading-clients').addClass('label-success');
			},
			error: app.errorHandlerView.handleError()
		}), this.options.systemScopeList.fetchIfNeeded({
			success: function(e) {
				$('#loading-scopes').addClass('label-success');
			},
			error: app.errorHandlerView.handleError()
		})).done(function() {
			$('#loadingbox').sheet('hide');
			callback();
		});
	},

	events: {
		"click .refresh-table": "refreshTable"
	},

	render: function(eventName) {
		$(this.el).html($('#tmpl-whitelist-table').html());

		var _self = this;

		_.each(this.model.models, function(whiteList) {

			// look up client
			var client = _self.options.clientList.getByClientId(whiteList.get('clientId'));

			// if there's no client ID, this is an error!
			if (client != null) {
				var view = new WhiteListView({
					model: whiteList,
					client: client,
					systemScopeList: _self.options.systemScopeList
				});
				view.parentView = _self;
				$('#whitelist-table', _self.el).append(view.render().el);
			}

		}, this);

		this.togglePlaceholder();
		$(this.el).i18n();
		return this;
	},

	togglePlaceholder: function() {
		if (this.model.length > 0) {
			$('#whitelist-table', this.el).show();
			$('#whitelist-table-empty', this.el).hide();
		} else {
			$('#whitelist-table', this.el).hide();
			$('#whitelist-table-empty', this.el).show();
		}
	},

	refreshTable: function(e) {
		e.preventDefault();
		var _self = this;
		$('#loadingbox').sheet('show');
		$('#loading').html('<span class="label" id="loading-whitelist">' + $.t('whitelist.whitelist') + '</span> ' + '<span class="label" id="loading-clients">' + $.t('common.clients') + '</span> ' + '<span class="label" id="loading-scopes">' + $.t('common.scopes') + '</span> ');

		$.when(this.model.fetch({
			success: function(e) {
				$('#loading-whitelist').addClass('label-success');
			},
			error: app.errorHandlerView.handleError()
		}), this.options.clientList.fetch({
			success: function(e) {
				$('#loading-clients').addClass('label-success');
			},
			error: app.errorHandlerView.handleError()
		}), this.options.systemScopeList.fetch({
			success: function(e) {
				$('#loading-scopes').addClass('label-success');
			},
			error: app.errorHandlerView.handleError()
		})).done(function() {
			$('#loadingbox').sheet('hide');
			_self.render();
		});
	}
});

var WhiteListView = Backbone.View.extend({
	tagName: 'tr',

	initialize: function(options) {
		this.options = options;
		if (!this.template) {
			this.template = _.template($('#tmpl-whitelist').html());
		}

		if (!this.scopeTemplate) {
			this.scopeTemplate = _.template($('#tmpl-scope-list').html());
		}

		if (!this.moreInfoTemplate) {
			this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html());
		}

		this.model.bind('change', this.render, this);
	},

	render: function(eventName) {

		var json = {
			whiteList: this.model.toJSON(),
			client: this.options.client.toJSON()
		};

		this.$el.html(this.template(json));

		$('.scope-list', this.el).html(this.scopeTemplate({
			scopes: this.model.get('allowedScopes'),
			systemScopes: this.options.systemScopeList
		}));

		$('.client-more-info-block', this.el).html(this.moreInfoTemplate({
			client: this.options.client.toJSON()
		}));

		this.$('.dynamically-registered').tooltip({
			title: $.t('common.dynamically-registered')
		});

		$(this.el).i18n();
		return this;
	},

	events: {
		'click .btn-edit': 'editWhitelist',
		'click .btn-delete': 'deleteWhitelist',
		'click .toggleMoreInformation': 'toggleMoreInformation'
	},

	editWhitelist: function(e) {
		e.preventDefault();
		app.navigate('admin/whitelist/' + this.model.get('id'), {
			trigger: true
		});
	},

	deleteWhitelist: function(e) {
		e.preventDefault();

		if (confirm($.t('whitelist.confirm'))) {
			var _self = this;

			this.model.destroy({
				dataType: false,
				processData: false,
				success: function() {
					_self.$el.fadeTo("fast", 0.00, function() { // fade
						$(this).slideUp("fast", function() { // slide up
							$(this).remove(); // then remove from the DOM
							// check the placeholder in case it's empty now
							_self.parentView.togglePlaceholder();
						});
					});
				},
				error: app.errorHandlerView.handleError()
			});

			_self.parentView.delegateEvents();
		}

		return false;
	},

	toggleMoreInformation: function(e) {
		e.preventDefault();
		if ($('.moreInformation', this.el).is(':visible')) {
			// hide it
			$('.moreInformation', this.el).hide('fast');
			$('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-right');
			$('.moreInformationContainer', this.el).removeClass('alert').removeClass('alert-info').addClass('muted');

		} else {
			// show it
			$('.moreInformation', this.el).show('fast');
			$('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-down');
			$('.moreInformationContainer', this.el).addClass('alert').addClass('alert-info').removeClass('muted');
		}
	},

	close: function() {
		$(this.el).unbind();
		$(this.el).empty();
	}
});

var WhiteListFormView = Backbone.View.extend({
	tagName: 'span',

	initialize: function(options) {
		this.options = options;
		if (!this.template) {
			this.template = _.template($('#tmpl-whitelist-form').html());
		}

		this.scopeCollection = new Backbone.Collection();

		this.listWidgetViews = [];

	},

	load: function(callback) {

		if (this.options.client) {
			// we know what client we're dealing with already
			if (this.model.isFetched && this.options.client.isFetched) {
				callback();
				return;
			}

			$('#loadingbox').sheet('show');
			$('#loading').html('<span class="label" id="loading-whitelist">' + $.t('whitelist.whitelist') + '</span> ' + '<span class="label" id="loading-clients">' + $.t('common.clients') + '</span> ' + '<span class="label" id="loading-scopes">' + $.t('common.scopes') + '</span> ');

			$.when(this.model.fetchIfNeeded({
				success: function(e) {
					$('#loading-whitelist').addClass('label-success');
				},
				error: app.errorHandlerView.handleError()
			}), this.options.client.fetchIfNeeded({
				success: function(e) {
					$('#loading-clients').addClass('label-success');
				},
				error: app.errorHandlerView.handleError()
			}), this.options.systemScopeList.fetchIfNeeded({
				success: function(e) {
					$('#loading-scopes').addClass('label-success');
				},
				error: app.errorHandlerView.handleError()
			})).done(function() {
				$('#loadingbox').sheet('hide');
				callback();
			});

		} else {
			// we need to get the client information from the list

			if (this.model.isFetched && this.options.clientList.isFetched && this.options.systemScopeList.isFetched) {

				var client = this.options.clientList.getByClientId(this.model.get('clientId'));
				this.options.client = client;

				callback();
				return;
			}

			$('#loadingbox').sheet('show');
			$('#loading').html('<span class="label" id="loading-whitelist">' + $.t('whitelist.whitelist') + '</span> ' + '<span class="label" id="loading-clients">' + $.t('common.clients') + '</span> ' + '<span class="label" id="loading-scopes">' + $.t('common.scopes') + '</span> ');

			var _self = this;

			$.when(this.model.fetchIfNeeded({
				success: function(e) {
					$('#loading-whitelist').addClass('label-success');
				},
				error: app.errorHandlerView.handleError()
			}), this.options.clientList.fetchIfNeeded({
				success: function(e) {
					$('#loading-clients').addClass('label-success');
				},
				error: app.errorHandlerView.handleError()
			}), this.options.systemScopeList.fetchIfNeeded({
				success: function(e) {
					$('#loading-scopes').addClass('label-success');
				},
				error: app.errorHandlerView.handleError()
			})).done(function() {

				var client = _self.options.clientList.getByClientId(_self.model.get('clientId'));
				_self.options.client = client;

				$('#loadingbox').sheet('hide');
				callback();
			});

		}

	},

	events: {
		'click .btn-save': 'saveWhiteList',
		'click .btn-cancel': 'cancelWhiteList',

	},

	saveWhiteList: function(e) {
		e.preventDefault();
		$('.control-group').removeClass('error');

		// sync any leftover collection items
		_.each(this.listWidgetViews, function(v) {
			v.addItem($.Event('click'));
		});

		// process allowed scopes
		var allowedScopes = this.scopeCollection.pluck("item");

		this.model.set({
			clientId: this.options.client.get('clientId')
		}, {
			silent: true
		});

		var valid = this.model.set({
			allowedScopes: allowedScopes
		});

		if (valid) {
			var _self = this;
			this.model.save({}, {
				success: function() {
					app.whiteListList.add(_self.model);
					app.navigate('admin/whitelists', {
						trigger: true
					});
				},
				error: app.errorHandlerView.handleError()
			});
		}

		return false;

	},

	cancelWhiteList: function(e) {
		e.preventDefault();
		// TODO: figure out where we came from and go back there instead
		if (this.model.get('id') == null) {
			// if it's a new whitelist entry, go back to the client listing page
			app.navigate('admin/clients', {
				trigger: true
			});
		} else {
			// if we're editing a whitelist, go back to the whitelists page
			app.navigate('admin/whitelists', {
				trigger: true
			});
		}
	},

	render: function(eventName) {

		var json = {
			whiteList: this.model.toJSON(),
			client: this.options.client.toJSON()
		};

		this.$el.html(this.template(json));

		this.listWidgetViews = [];

		var _self = this;
		// build and bind scopes
		_.each(this.model.get("allowedScopes"), function(scope) {
			_self.scopeCollection.add(new Backbone.Model({
				item: scope
			}));
		});

		var scopeView = new ListWidgetView({
			placeholder: $.t('whitelist.whitelist-form.scope-placeholder'),
			autocomplete: this.options.client.get("scope"),
			helpBlockText: $.t('whitelist.whitelist-form.scope-help'),
			collection: this.scopeCollection
		});
		$("#scope .controls", this.el).html(scopeView.render().el);
		this.listWidgetViews.push(scopeView);

		$(this.el).i18n();
		return this;

	}

});

ui.routes.push({
	path: "admin/whitelists",
	name: "whiteList",
	callback: function() {

		if (!isAdmin()) {
			this.root();
			return;
		}

		this.updateSidebar('admin/whitelists');

		this.breadCrumbView.collection.reset();
		this.breadCrumbView.collection.add([{
			text: $.t('admin.home'),
			href: ""
		}, {
			text: $.t('whitelist.manage'),
			href: "manage/#admin/whitelists"
		}]);

		var view = new WhiteListListView({
			model: this.whiteListList,
			clientList: this.clientList,
			systemScopeList: this.systemScopeList
		});

		view.load(function() {
			$('#content').html(view.render().el);
			view.delegateEvents();
			setPageTitle($.t('whitelist.manage'));
		});

	}
});

ui.routes.push({
	path: "admin/whitelist/new/:cid",
	name: "newWhitelist",
	callback: function(cid) {

		if (!isAdmin()) {
			this.root();
			return;
		}

		this.breadCrumbView.collection.reset();
		this.breadCrumbView.collection.add([{
			text: $.t('admin.home'),
			href: ""
		}, {
			text: $.t('whitelist.manage'),
			href: "manage/#admin/whitelists"
		}, {
			text: $.t('whitelist.new'),
			href: "manage/#admin/whitelist/new/" + cid
		}]);

		this.updateSidebar('admin/whitelists');

		var whiteList = new WhiteListModel();

		var client = this.clientList.get(cid);
		if (!client) {
			client = new ClientModel({
				id: cid
			});
		}

		var view = new WhiteListFormView({
			model: whiteList,
			client: client,
			systemScopeList: this.systemScopeList
		});

		view.load(function() {

			// set the scopes on the model now that everything's loaded
			whiteList.set({
				allowedScopes: client.get('scope')
			}, {
				silent: true
			});

			$('#content').html(view.render().el);
			view.delegateEvents();
			setPageTitle($.t('whitelist.manage'));
		});

	}
});

ui.routes.push({
	path: "admin/whitelist/:id",
	name: "editWhitelist",
	callback: function(id) {

		if (!isAdmin()) {
			this.root();
			return;
		}

		this.breadCrumbView.collection.reset();
		this.breadCrumbView.collection.add([{
			text: $.t('admin.home'),
			href: ""
		}, {
			text: $.t('whitelist.manage'),
			href: "manage/#admin/whitelists"
		}, {
			text: $.t('whitelist.edit'),
			href: "manage/#admin/whitelist/" + id
		}]);

		this.updateSidebar('admin/whitelists');

		var whiteList = this.whiteListList.get(id);
		if (!whiteList) {
			whiteList = new WhiteListModel({
				id: id
			});
		}

		var view = new WhiteListFormView({
			model: whiteList,
			clientList: this.clientList,
			systemScopeList: this.systemScopeList
		});

		view.load(function() {
			$('#content').html(view.render().el);
			view.delegateEvents();
			setPageTitle($.t('whitelist.manage'));
		});

	}

});

ui.templates.push('resources/template/whitelist.html');

ui.init.push(function(app) {
	app.whiteListList = new WhiteListCollection();
});
