/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

 
define(function(require) {
    'use strict';
	var Backbone	= require('backbone');
	var App			= require('App');
	
	var MAppState	= require('models/VAppState');
	var XAGlobals	= require('utils/XAGlobals');

	return Backbone.Marionette.Controller.extend({

		initialize: function( options ) {
			console.log("initialize a Controller Controller");
			var vTopNav 	= require('views/common/TopNav');
			var vProfileBar = require('views/common/ProfileBar');
			var vFooter 	= require('views/common/Footer');

			App.rTopNav.show(new vTopNav({
				model : App.userProfile,
				appState : MAppState
			}));

			App.rTopProfileBar.show(new vProfileBar({}));

			App.rFooter.show(new vFooter({}));
		},

		dashboardAction: function (action) {
            console.log('dashboard action called..');
			var vDashboardLayout	= require('views/common/DashboardLayout');
            MAppState.set({
				'currentTab' : XAGlobals.AppTabs.Dashboard.value
			});
			
            App.rContent.show(new vDashboardLayout({}));
        },
	   
	   //************** Analytics(reports)  Related *********************/
	   userAccessReportAction : function(){
		   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.Analytics.value });
		   var view				= require('views/reports/UserAccessLayout');
		   var VXResourceList 	= require('collections/VXResourceList');
		   var VXGroupList		= require('collections/VXGroupList');
		   var VXUserList		= require('collections/VXUserList');
		   var resourceList 	= new VXResourceList([],{
			   queryParams : {
				   //'resourceType' : XAEnums.AssetType.ASSET_HDFS.value,
				   //'assetId' : assetId 
			   }
		   });
		   var that 		= this;
		   this.groupList 	= new VXGroupList();
		   this.userList 	= new VXUserList();
		   resourceList.setPageSize(200, {fetch : false});
		   resourceList.fetch({
			   async:false,
			   cache : false
		   }).done(function(){
				that.groupList.fetch({
						async:false,
						cache:false
					}).done(function(){
					that.userList.fetch({
						async:false,
						cache:false
					}).done(function(){
						if(App.rContent.currentView)
							   App.rContent.currentView.close();
						App.rContent.show(new view({
							collection : resourceList,
							groupList :that.groupList,
							userList :that.userList
						}));
					});
				});
		   });
	   },
	   auditReportAction : function(tab){
		   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.Audit.value });
		   var view					= require('views/reports/AuditLayout');
		   var VXAccessAuditList 	= require('collections/VXAccessAuditList');
		   var accessAuditList 		= new VXAccessAuditList();
		   App.rContent.show(new view({
			   accessAuditList : accessAuditList,
			   tab :tab
		   }));
		   if(tab == 'bigData'){
			  accessAuditList.fetch({
				 cache : false,
				 async:true
			   });
		   }
	   },
	   loginSessionDetail : function(type, id){
		   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.Audit.value });
		   var view					= require('views/reports/LoginSessionDetail');
		   var VXAuthSessionList	= require('collections/VXAuthSessionList');
		   var authSessionList 		= new VXAuthSessionList();
		   authSessionList.fetch({
			   data : {id : id}
		   }).done(function(){
			   App.rContent.show(new view({
				   model : authSessionList.first()
			   }));
		   });
	   },
	   //************** UserProfile Related *********************/
	   userProfileAction : function(){
		   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.None.value });
		   var view				= require('views/user/UserProfile');
		   
		   App.rContent.show(new view({
			   model : App.userProfile
		   }));

	   },
	   
	   /************** UserORGroups Related *********************/
	   userManagerAction :function(tab){
		   MAppState.set({
				'currentTab' : XAGlobals.AppTabs.Users.value
			});
		   var view 		= require('views/users/UserTableLayout');
		   var VXUserList	= require('collections/VXUserList');
		   var userList 	= new VXUserList();
		   
		   App.rContent.show(new view({
			   collection : userList,
			   tab :tab
		   }));
		   userList.fetch({
			   cache:true
		   });
	   },
	   userCreateAction : function(){
		   MAppState.set({
				'currentTab' : XAGlobals.AppTabs.Users.value
			});
		   var view 		= require('views/users/UserCreate');
		   var VXUser		= require('models/VXUser');
		   var VXUserList	= require('collections/VXUserList');
		   var VXGroupList	= require('collections/VXGroupList');

		   var groupList = new VXGroupList();
		   var user 	 = new VXUser();
		   user.collection = new VXUserList();
	   	   groupList.fetch({cache:true,async:false}).done(function(){
			   App.rContent.show(new view({
				   model : user,
				   groupList :groupList
			   }));
		   });   
	   },
	   userEditAction : function(userId){
		   MAppState.set({
				'currentTab' : XAGlobals.AppTabs.Users.value
			});
		   var view 		= require('views/users/UserCreate');
		   var VXUser		= require('models/VXUser');
		   var VXUserList	= require('collections/VXUserList');

		   var user 	 = new VXUser({id : userId});
		   
		   user.collection = new VXUserList();
		   user.fetch({cache : true}).done(function(){
			   App.rContent.show(new view({
				   model : user,
			   }));
		   });
	   },
	   groupCreateAction : function(){
		   MAppState.set({
				'currentTab' : XAGlobals.AppTabs.Users.value
			});
		   var view 		= require('views/users/GroupCreate');
		   var VXGroup		= require('models/VXGroup');
		   var VXGroupList	= require('collections/VXGroupList');
		   
		   var group 		= new VXGroup();
		   group.collection = new VXGroupList();
		   App.rContent.show(new view({
			   model : group
		   }));
	   },
	   groupEditAction : function(groupId){
		   MAppState.set({
				'currentTab' : XAGlobals.AppTabs.Users.value
			});
		   var view 		= require('views/users/GroupCreate');
		   var VXGroup		= require('models/VXGroup');
		   var VXGroupList	= require('collections/VXGroupList');
		   
		   var group 		= new VXGroup({id : groupId});
		   group.collection = new VXGroupList();
		   
		   group.fetch({cache : true}).done(function(){
			   App.rContent.show(new view({
				   model : group
			   }));
		   });	   
	   },


   	   /************************************************************/
   	   //************** Generic design Related *********************/
   	   /************************************************************/

	   serviceManagerAction :function(){
		   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.PolicyManager.value });
		   console.log('Policy Manager action called..');
		   var view 				= require('views/policymanager/ServiceLayout');
		   var RangerServiceDefList	= require('collections/RangerServiceDefList');
		   var collection 			= new RangerServiceDefList();
		   collection.queryParams.sortBy = 'id';
		   collection.fetch({
			   cache : false,
			   async:false
		   }).done(function(){
			   if(App.rContent.currentView) App.rContent.currentView.close();
			   //TODO FROM SERVER SIDE IT SHOULD GIVE SORTBY `ID` BY DEFAULT
//			   collection = collection.sort()
			   App.rContent.show(new view({
				   collection : collection
			   }));
		   });
	   },

	   serviceCreateAction :function(serviceTypeId){
    	   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.PolicyManager.value });
		   var view				= require('views/service/ServiceCreate');
		   var RangerServiceDef	= require('models/RangerServiceDef');
		   var RangerService	= require('models/RangerService');
		   
		   var rangerServiceDefModel	= new RangerServiceDef({id:serviceTypeId});
		   var rangerServiceModel 	= new RangerService();

		   App.rContent.show(new view({
			   model 		: rangerServiceModel,
			   serviceTypeId : serviceTypeId
		   }));
	   },
	   serviceEditAction :function(serviceTypeId, serviceId){
    	   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.PolicyManager.value });
		   var view				= require('views/service/ServiceCreate');
		   var RangerServiceDef	= require('models/RangerServiceDef');
		   var RangerService	= require('models/RangerService');
		   
		   var rangerServiceDefModel	= new RangerServiceDef({ id : serviceTypeId });
		   var rangerService = new RangerService({ 'id' : serviceId });

		   rangerService.fetch({
			   cache:false
		   }).done(function(){
			   App.rContent.show(new view({
				   model 			: rangerService,
				   serviceTypeId	:serviceTypeId
			   }));
		   });
	   },
	   
	   policyManageAction :function(serviceId){
		   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.PolicyManager.value });
		   var XAUtil			= require('utils/XAUtils');
		   var view 			= require('views/policies/RangerPolicyTableLayout');
		   var RangerService	= require('models/RangerService');
		   var RangerPolicyList	= require('collections/RangerPolicyList');
		   
		   var rangerService = new RangerService({id : serviceId});
		   var rangerPolicyList = new RangerPolicyList();
		   /*var rangerPolicyList = new RangerPolicyList([],{
			   queryParams : {
				   'serviceId' : serviceId 
			   }
		   });*/
		   rangerPolicyList.url = XAUtil.getServicePoliciesURL(serviceId);
		   
		   rangerService.fetch({
			  cache : false,
			  async : false
		   });
		   
		   rangerPolicyList.fetch({
			   cache : false,
		   }).done(function(){
			   App.rContent.show(new view({
				   collection : rangerPolicyList,
				   rangerService : rangerService
			   }));
		   });   
	   },
	   RangerPolicyCreateAction :function(serviceId){
    	   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.PolicyManager.value });

		   var view 			= require('views/policies/RangerPolicyCreate');
		   var RangerService	= require('models/RangerService');
		   var RangerPolicy		= require('models/RangerPolicy');
		   
		   var rangerService = new RangerService({id : serviceId});
		   rangerService.fetch({
				  cache : false,
		   }).done(function(){
			   App.rContent.show(new view({
				   model : new RangerPolicy(),
				   rangerService : rangerService,
			   }));
		   });
	   },
	   RangerPolicyEditAction :function(serviceId, policyId){
    	   MAppState.set({ 'currentTab' : XAGlobals.AppTabs.PolicyManager.value });

		   var view 			= require('views/policies/RangerPolicyCreate');
		   var RangerService	= require('models/RangerService');
		   var RangerPolicy		= require('models/RangerPolicy');
		   
		   var rangerService = new RangerService({id : serviceId});
		   var rangerPolicy = new RangerPolicy({ id : policyId});
		   rangerService.fetch({
			   cache : false,
			   async : false,
		   });
		   rangerPolicy.fetch({
				  cache : false,
		   }).done(function(){
			   App.rContent.show(new view({
				   model : rangerPolicy,
				   rangerService :rangerService
			   }));
		   });
	   },
	   
	});
});
