/* ProjectDescription */

var ProjectDescription = Base.extend({

	constructor: function(title, expectedStartDate, expectedEndDate, objective, uri, needsLogin) {
		this.base();
		this.properties = {};
		this.properties.title = title;
		this.properties.expectedStartDate = this.dateFromJSONValue(expectedStartDate);
		this.properties.expectedEndDate = this.dateFromJSONValue(expectedEndDate);
		this.properties.info = objective;
		this.properties.needsLogin = needsLogin;
		this.objectID = {uri:uri};
	},
	
	dateFromJSONValue: function(value)
	{
		return value ? new Date(1000*value) : null;
	},
	
	valueForKey: function(key){
		return this.properties[key];
	},
	
	sortValueForKey: function(key){
		return this.properties[key];
	},
	
	needsLogin: function(){
		return this.properties.needsLogin;
	},
	
	title: function() {
		return this.properties.title;
	},

	uri: function() {
		return this.objectID.uri;
	}
	
 }); 

/* Project List */

var ProjectListController = Base.extend({	

	constructor: function(mainView, 
						  listContainer, 
						  environment, 
						  tableColumns, 
						  fetchProjectListDescriptionAction, 
						  usernamesInProjectAction, 
						  tryToLoginAction, 
						  tryToLoginToProjectAction, 
						  openProjectActionURL, 
						  openCombinedProjectsActionURL, 
						  logoutURL, 
						  usernameElement, 
						  loginButton, 
						  logoutButton, 
						  openProjectsButton, 
						  showProjectURLButton, 
						  autologin, 
						  autologinURI, 
						  canCombineProjects) {
		this.base();
		this.showLogin							= false;
		this.username							= null;
		this.mainView							= mainView;
		this.listContainer						= listContainer;
		this.environment						= environment;				
		this.fetchProjectListDescriptionAction	= fetchProjectListDescriptionAction;
		this.tryToLoginAction					= tryToLoginAction;
		this.usernamesInProjectAction			= usernamesInProjectAction;
		this.tryToLoginToProjectAction			= tryToLoginToProjectAction;
		this.logoutURL							= logoutURL;
		this.openProjectActionURL				= openProjectActionURL;
		this.openCombinedProjectsActionURL		= openCombinedProjectsActionURL;
		this.usernameElement					= usernameElement;
		this.loginButton						= PWUtils.makeMultiStateButton(loginButton);
		this.logoutButton						= logoutButton;
		this.openProjectsButton					= PWUtils.makeMultiStateButton(openProjectsButton);
		this.showProjectURLButton				= PWUtils.makeMultiStateButton(showProjectURLButton);

		this.autologin							= autologin;
		this.autologinURI						= autologinURI;
		this.canCombineProjects					= canCombineProjects;
		
		this.loginButton.setEnabled(false);
		this.openProjectsButton.setEnabled(false);
		this.showProjectURLButton.setEnabled(false);
        		
		this.outlineController = new OutlineController();
		this.outlineController.setSortDescriptors([{key:'title', ascending: true}]);
		this.outlineView = new OutlineView(this.listContainer, this.outlineController, 20, null, true, environment, false, this);
		this.outlineView.setAlternateRows(true);

		this.outlineView.setColumnsAndOutlineColumnKey(tableColumns, tableColumns[0].key);
		this.outlineView.setYScrollBarType("auto");
		this.outlineView.setXScrollBarType("auto");	
		this.outlineView.setEnableDrags(false);			
		this.outlineView.setHeaderHeight(20);
		this.outlineView.outlineColumnPadding = 4;
		this.outlineView.setSingleSelection(!this.canCombineProjects);
		
		this.windowResizedActionEventListener	= this.windowResizedAction.bindAsEventListener(this);
		PWUtils.observe(window, "resize", this.windowResizedActionEventListener, true);
										
		this.refresh();
	},
	
	windowResizedAction: function(event) {
		this.outlineView.refresh();
	},

	projectListDescriptionFromJSON: function(json)
	{
		var description = eval("("+json+")");
		var projectList = [];
		var p = description.projectList;
		p.each(function(dict) {
			projectList.push(new ProjectDescription(dict.title, dict.expectedStartDate, dict.expectedEndDate, dict.objective, dict.uri, dict.needsLogin));
		});
		description.projectList = projectList;
		return description;
	},
	
	projectWithURIFromProjects: function(URI, projects){
		return projects.detect(function(project){
			// In Merlin Server the autologinURI can be the title of the project.
			return project.objectID.uri == URI || project.properties.title == URI;
		});
	},

	selectProjectWithURI: function(URI){
		var project = this.projectWithURIFromProjects(URI, this.outlineController.rootObjects);		
		if(project) {
			this.outlineController.setSelectedObjects([project]);
			this.outlineView.refresh();			
			return true;
		}
		return false;
	},
										
	autologinIfNeeded: function() {
		if(this.autologin) {
			this.autologin = false;
			if(this.autologinURI){
				if(this.selectProjectWithURI(this.autologinURI)){
					this.openSelectedProjects();
				}else{
					// If the project is not visible (maybe it no longer exists or is not visible for anonymous users),
					// show the login dialog:
					var controller = this;
					this.login(function(){
						if(controller.selectProjectWithURI(controller.autologinURI))
							controller.openSelectedProjects();
					});
				}
			} 
		}
	},

	refresh: function() {
		var description = this.projectListDescriptionFromJSON(this.fetchProjectListDescriptionAction());
		var username = description['username'];
		this.username = username ? username : null;
		this.showLogin = description['showLogin'];

		this.loginButton.setEnabled(this.showLogin);
		this.logoutButton.style.display = username ? "block" : "none";
		this.loginButton.style.display = !username ? "block" : "none";
						
		var theProjects = description.projectList;
		this.outlineController.setRootObjects(theProjects);
		this.outlineView.refresh();
		this.autologinIfNeeded();
	},

	tryToLoginToProject: function(me, aProject, aUsername, aPassword)
	{
		var options = {uri:aProject.uri()};
		if(aUsername)
			options["username"] = aUsername; 
		if(aPassword)
			options["password"] = aPassword; 
		var result = eval("("+me.tryToLoginToProjectAction(options)+")");
		return result.accepted;
	},

	combineProjects: function(projects)
	{
		var uris = "";
		for(var i=0; i<projects.length; i++)
		{
			var prefix = i>0 ? "&" : "";
			uris += prefix+"uri="+projects[i].uri();
		}
		var newLocation = this.openCombinedProjectsActionURL+"?"+uris;	
		window.location = newLocation;
	},

	openProject: function(project)
	{
		window.location = this.openProjectActionURL+"?uri="+project.uri();	
	},

	handleDoubleClickedProject: function(project)
	{
		if(project.needsLogin()) {
			if(this.username && this.tryToLoginToProject(this, project))
				this.openProject(project);
			else {				
				var uri = project.uri();
				var users = "("+this.usernamesInProjectAction({uri:uri})+")";
				var usernames = eval(users);
				var loginTitle = stringWithFormat(this.environment.localizedString("Login to project '%@'"), project.title());
				var me = this;
				var onValidate = function(username, password, context) {					
					var accepted = me.tryToLoginToProject(me, project, username, password);
					if(accepted)
						me.openProject(project);
					return accepted;
				} 
				runLoginDialog(loginTitle, onValidate, null, this.environment, null, null, usernames);
			}
		} else
			this.openProject(project);
	},

	outlineShouldEditObjectProperty: function(outline, object, key){
		this.handleDoubleClickedProject(object);
		return false;
	},

	outlineDidChangeSelection: function(outline) {
        var selectedProjectsCount = this.outlineController.selectedObjects.length;
		this.openProjectsButton.setEnabled( selectedProjectsCount );
		this.showProjectURLButton.setEnabled( selectedProjectsCount == 1 );
	},

	openSelectedProjects: function() {
		if(this.outlineController.selectedObjects.length == 1)
			this.handleDoubleClickedProject(this.outlineController.selectedObjects[0]);
		else if(this.outlineController.selectedObjects.length > 1)
			this.combineProjects(this.outlineController.selectedObjects);
	},

    showProjectURL: function()
    {
        var project = this.outlineController.selectedObjects.length ? this.outlineController.selectedObjects[0] : null;  
        if(project)
        {
            var title = project.valueForKey("title");
            var url = "http://"+window.location.host+"/wa/default?title="+encodeURIComponent(title);
            var alertText = "URL: "+url;
            var alertDescription = stringWithFormat(this.environment.localizedString("ProjectURLAlertDescription '%s'"), title);
            runAlert(alertText, alertDescription, null, null, null);
        }
    },

	login: function(onSuccess, title) {
		var me = this;
		var onValidate = function(username, password, context) {
			var result = eval("("+me.tryToLoginAction({username:username, password:password})+")");
			if(result.accepted){
				me.username = username;
				me.usernameElement.innerHTML = me.username;
				me.refresh();
			}
			if(onSuccess)
				onSuccess();
			return result.accepted;
		} 
		if(!title)
			title = this.environment.localizedString("Login");
		runLoginDialog(title, onValidate, null, this.environment, this.username || '', '');
	},
	
	logout: function() {
		window.location = this.logoutURL;
	}

});


/* 
	Attach Keyboard events to modal dialogs

	TODO: Move the whole keyboard stuff into an own component 
*/

shortcut.add('esc', function(){});		
shortcut.add('return', function(){});		
shortcut.add('enter', function(){});		

shortcut.absorbKeys = function(event, keys) {
	if(modalWindow()){
		modalWindow().handleKeyboardEvent(event, keys);
		return true;
	}
	return false;
}
