/* Copyright 2009 Palm, Inc.  All rights reserved. */

var TaskAssistant = Class.create(
{	
    initialize: function(pendingMods)
	{
		this._pendingMods = pendingMods;
    },
	
    setup: function()
	{
        var model = State.task;
		this.task = model;
		 
        // Subject
        this.subjectAttributes = 
		{
            hintText: $L('Task name...'),
            focus: !model.id,
			multiline: true,
            textFieldMode: 'sentence-case',
			changeOnKeyPress: true,
			enterSubmits: true,
        };
        this.subjectModel = 
		{
            value: this._pendingMods && this._pendingMods.subject ? this._pendingMods.subject : model.subject
        };
        
        // Completed
        this.completedAttributes = {};
        this.completedModel = 
		{
            value: model.completed
        };
        
        // Check box color
        this.checkBoxElement = this.controller.get('completed');
        if (model.priority) 
		{
            this.checkBoxElement.addClassName(Task.priorityName(model.priority));
        }
        
        // Priority
        this.priorities = [{
            label: $L('High'),
            value: 1,
            icon: 'checkbox-high'
        }, {
            label: $L('Normal'),
            value: 2,
            icon: 'checkbox-normal'
        }, {
            label: $L('Low'),
            value: 3,
            icon: 'checkbox-low'
        }];
        
        this.priorityAttributes = 
		{
            label: $L('Priority'),
            choices: this.priorities
        };
        this.priorityModel = 
		{
            value: model.priority ? model.priority : 2
        };
        
        // Task List name
        // For now only the current list
        // We update the content after we load
		// We also change the All Tasks name to Unfiled
		var tasklistname = TaskList.getNameWithDefault(State.taskList);
        this.taskListAttributes = {
			label: $L('List'),
            choices: [
				{
					value: 1,
					label: tasklistname == $L('All tasks') ? '' : tasklistname,
				}
			]
        };
        this.taskListModel = {
            value: 1
        };
        
        // Notes
        this.notesAttributes = {
            hintText: model.id ? '' : $L('Notes...'),
            multiline: true,
            textFieldMode: 'sentence-case',
			changeOnKeyPress: true,
			focus: !!model.id,
        };
        this.notesModel = {};
        this.controller.setupWidget('completed', this.completedAttributes, this.completedModel);
        this.controller.setupWidget('subject', this.subjectAttributes, this.subjectModel);
        this.controller.setupWidget('completed', this.completedAttributes, this.completedModel);
        this.controller.setupWidget('priority', this.priorityAttributes, this.priorityModel);
        this.controller.setupWidget('taskList', this.taskListAttributes, this.taskListModel);
        this.controller.setupWidget('notes', this.notesAttributes, this.notesModel);
        
        var dueDateText = this.getInitialDueDateText(model);
        
        this.dueDateElement = this.controller.get('task_duedate');
        var button = Mojo.View.render({
            object: {
                text: dueDateText,
                buttonId: 'duedateButton'
            },
            template: "task/popupbutton"
        });
        this.dueDateElement.insert(button);
        this.controller.get('task_duebox').observe(Mojo.Event.tap, this.onDueDateTap.bindAsEventListener(this));
        
        // Menu
/*
        this.appMenuModel = 
		{
            visible: true,
            label: $L('Task menu'),
            items: [{
                label: $L('Delete Task'),
                command: 'delete'
            }]
        };
        this.controller.setupWidget(Mojo.Menu.appMenu, undefined, this.appMenuModel);
*/
		new Weave.Utilities.AppMenu(this).addEdit().addItem($L('Delete Task'), this.handleDeleteCmd.bind(this)).addHelp();
		
		this._onSceneDeactivate = this._onSceneDeactivate.bindAsEventListener(this);
        
        this.subjectElement = this.controller.get('subject');
        this.notesElement = this.controller.get('notes');
        this.subjectElement.observe(Mojo.Event.propertyChange, this.subjectChanged.bind(this));
        this.controller.listen('completed', Mojo.Event.propertyChange, this.completedChanged.bind(this));
        // this.controller.listen('dueDate', Mojo.Event.propertyChange, this.dueDateChanged.bind(this));
        this.controller.listen('priority', Mojo.Event.propertyChange, this.priorityChanged.bind(this));
        this.notesElement.observe(Mojo.Event.propertyChange, this.notesChanged.bind(this));
        this.controller.listen('taskList', Mojo.Event.propertyChange, this.taskListChanged.bind(this));
        
        // Lazily load the object
        // For the other information
		Mojo.Log.info("Should I get task?");
        if (model.id) 
		{
			Mojo.Log.info("** YES");
            // Don't allow saving until we get the information
            // will allow saving once the task is loaded
			model.load(this, this.onTaskLoaded.bind(this));
        }
        else 
		{
			Mojo.Log.info("** NO %j", this._pendingMods);
			var newmodel = new Task(model);
			this._newmodel = newmodel;
			
			if (!model.priority) 
			{
                newmodel.priority = 2;
				model.priority = newmodel.priority;
            }
            // Initialize task list id
			newmodel.taskListId = (State.taskList ? State.taskList.id : undefined);
			model.taskListId = newmodel.taskListId;
			
			// If we have a pending subject change, copy it into the new model
			// so it will be saved.
			if (this._pendingMods && this._pendingMods.subject)
			{
				newmodel.subject = this._pendingMods.subject;
			}
            
            // Get the task lists!
            this._loadTaskLists();
        }
    },
    
    cleanup: function()
	{
        Mojo.Log.info('TaskAssistant::cleanup');
        if (!this.saveTask())
		{
			// Didnt save the task - if this was new then we mark is as deleted
			if (!this.task.id)
			{
				this.task.update(this, { deleted: true });
			}
		}
    },
	
    /**
     * Also initialize the choice for the list
     * @param {Object} task
     */
    getInitialDueDateText: function(task){
        var dueDateText;
        if (task.dueDateText === '') {
            return task.dueDateText;
        }
        
        if (task.dueDate) {
            this.dueDateChoice = 'custom';
            var date = new Date(task.dueDate);
            dueDateText = Mojo.Format.formatDate(date, { date: 'default' });
        }
        else {
            this.dueDateChoice = 'none';
            dueDateText = $L('No due date');
        }
        return dueDateText;
    },
    
    onDueDateTap: function(e)
	{
        Mojo.Log.info('onDueDateTap');
        
        var date = new Date();
		//var format = $L("MM/dd");
		//function oDate(offset)
		//{
		//	var d = new Date();
		//	d.setTime(date.getTime() + offset);
		//	return d;
		//}
        var dueDateChoices = [{
            label: $L('No due date'),
            command: 'none'
        }, {
			label: $L('Today'),
            //label: $L('Today #{date}').interpolate({ date: Mojo.Format.formatDate(date, format) }),
            command: 'today'
        }, {
			label: $L('Tomorrow'),
            //label: $L('Tomorrow #{date}').interpolate({ date: Mojo.Format.formatDate(oDate(86400000), format) }),
            command: 'tomorrow'
        }, {
			label: $L('In one week'),
            //label: $L('In one week #{date}').interpolate({ date: Mojo.Format.formatDate(oDate(604800000), format) }),
            command: 'one_week'
        }, {
			label: $L('In one month'),
            //label: $L('In one month #{date}').interpolate({ date: Mojo.Format.formatDate(oDate(2592000000), format) }),
            command: 'one_month'
        }, {
            label: $L('Other...'),
            command: 'other'
        }];
        
        if (this.dueDateChoice == 'custom') 
		{
            dueDateChoices.unshift({
                label: Mojo.Format.formatDate(new Date(this.getCurrentDueDateMs()), { date: 'default' }),
                command: 'custom'
            });
        }
        this.controller.popupSubmenu({
            onChoose: this.onDueDateSelected.bind(this),
            placeNear: e.target,
            toggleCmd: this.dueDateChoice,
            items: dueDateChoices
        });
    },
    
    getCurrentDueDateMs: function()
	{
        return this._newmodel.dueDate ? this._newmodel.dueDate : undefined;
    },
    
    onDueDateSelected: function(value)
	{
        //log('onDueDateSelected: ' + value);
        if (value !== undefined && value != this.dueDateChoice || value == 'other') 
		{
            var dueDateText;
            var newDueDateMs;
            var today = new Date();
			today.setMilliseconds(0);
			today.setSeconds(0);
			today.setMinutes(0);
			today.setHours(0);
            var todayMs = today.getTime();
                        
            switch (value) 
			{
                case 'none':
                    dueDateText = $L('No due date');
                    newDueDateMs = null;
                    break;
                case 'today':
                    dueDateText = $L('Today');
                    newDueDateMs = todayMs;
                    break;
                case 'tomorrow':
                    dueDateText = $L('Tomorrow');
                    newDueDateMs = todayMs + 86400000;
                    break;
                case 'one_week':
                    newDueDateMs = todayMs + 604800000;
                    break;
                case 'two_weeks':
                    newDueDateMs = todayMs + 1209600000;
                    break;
                case 'one_month':
                    newDueDateMs = todayMs + 2592000000;
                    break;
                case 'other':
                    this.onDueDateOtherTap();
                    return;            
			}
            
            if (newDueDateMs === undefined) 
			{
                return;
            }
            this.dueDateChoice = value;
            this._newmodel.dueDate = newDueDateMs;
			            
            if (!dueDateText) 
			{
                dueDateText = Mojo.Format.formatDate(new Date(newDueDateMs), { date: 'default' });
            }
            
            this.updateButton(dueDateText);
        }
    },
    
    onTaskLoaded: function(status)
	{
        Mojo.Log.info("task loaded: %j", this.task);
		
		// Set a default priority if necessary
		if (!this.task.priority)
		{
			this.task.priority = 2;
		}
        
		// Create a new model using the old one as a template, but overwrite with newly loaded data
		// to fill in the gaps
		var newmodel = new Task(this.task);
        this._newmodel = newmodel;
		
        this.priorityModel.value = newmodel.priority;
        this.controller.modelChanged(this.priorityModel);
        this.updateCheckBoxColor(newmodel.priority);
        
		this.notesAttributes.hintText = $L('Notes...');
        this.notesModel.value = newmodel.notes;
        this.controller.modelChanged(this.notesModel);
        
        // Update completed if needed
        // This can happen when going from the dashboard
        if (newmodel.completed != this.completedModel.value) 
		{
            this.completedModel.value = newmodel.completed;
            this.controller.modelChanged(this.completedModel);
        }
         
        // Subject - needed when launched from task details
        this.subjectModel.value = newmodel.subject;
        this.controller.modelChanged(this.subjectModel);
        
        // due date!
        this.updateButton(this.getInitialDueDateText(newmodel));
        
        // Get the task lists!
        this._loadTaskLists();
/*        
        // Set the focus on notes unless subject is empty
        if (newmodel.subject) 
		{
            this.notesElement.mojo.focus();
        }
        else 
		{
            this.subjectElement.mojo.focus();
        }
*/
    },
    
    /**
     * Called once the task is loaded or when the priority is changed
     *
     * @param {Object} priority
     */
    updateCheckBoxColor: function(priority, priorityName)
	{
        this.checkBoxElement.removeClassName('high');
        this.checkBoxElement.removeClassName('low');
        this.checkBoxElement.removeClassName('normal');
        this.checkBoxElement.addClassName(priorityName ? priorityName : Task.priorityName(priority));
    },
	
	_loadTaskLists: function()
	{
		var self = this;
		TaskList.getAll(this, undefined, undefined, undefined, false, function(status, list)
		{
			self.taskListModel.value = self._newmodel.taskListId;
	        var taskLists = [];
	        for (var i = 0; i < list.length; i++) 
			{
	            var item = list[i];
	            taskLists.push({
					value: item.id,
					label: TaskList.getNameWithDefault(item)
				});
	            if (TaskList.isDefault(item) && self.taskListModel.value == 'alltasks') 
				{
	                self.taskListModel.value = item.id;
	            }
	        }
			
			self.taskListAttributes.choices = taskLists;
	        self.controller.modelChanged(self.taskListModel);
		});
    },
    
    saveTask: function()
	{
		var model = this.task;

		// If the task has changed (but not deleted), then we need to save it
		if (!model.deleted && model.update(this, this._newmodel))
		{
			// Fixup the subject if necessary
			if (!model.subject && !this._newmodel.subject)
			{
				model.update(this, { subject: Task.nameFromItem(model) });
			}
			
            // If we change dashboard task, force it to update
            if (model.id == State.dashboard.taskId)
			{
                State.dashboard.update(this, { taskId: model.id }, true);
            }

			Mojo.Log.info("Saving task %j", model);
			model.save(this);
			return true;
        }
		return false;
    },
    
    handleDeleteCmd: function()
	{
		var self = this;
		this.controller.showAlertDialog(
		{
	        onChoose: function(value) 
			{
				if (value == 'delete')
				{
				    if (self._newmodel.id) 
					{
			            self._newmodel.remove(self, function()
						{
							self.task.update(self, { deleted: true }); // Throw model away since we're deleting it
			                self.controller.stageController.popScene();
			            });
			        }
			        else 
					{
						self.task.update(self, { deleted: true }); // Throw model away since we're deleting it
			            self.controller.stageController.popScene();
			        }
				}
			},
	        //title: $L("Delete task"),
	        message: $L("Are you sure you want to delete this task?"),
	        choices:
			[
	             {label:$L('Delete'), value:'delete', type:'negative'},
	             {label:$L("Cancel"), value:'cancel', type:'dismiss'},
	        ]
        });
    },
    
/*
    handleCommand: function(event)
	{
		if (event.type == Mojo.Event.back)
		{
			// Save the task
			//this.saveTask();
		}
        else if (event.type == Mojo.Event.command) 
		{
            switch (event.command) 
			{
                case 'delete':
                    this.handleDeleteCmd();
                    Event.stop(event);
                    break;

                default:
                    break;
            }
        }
    },
*/
	
	_onSceneDeactivate: function()
	{
		this.cleanup();
	},
    
    subjectChanged: function(event)
	{
        this._newmodel.subject = event.value;
    },
    
    completedChanged: function(event)
	{
        this._newmodel.completed = event.value;
    },
    
    priorityChanged: function(event)
	{
        this._newmodel.priority = event.value - 0; // Make sure it is a number
        this.updateCheckBoxColor(this._newmodel.priority);
    },
    
    taskListChanged: function(event)
	{
        this._newmodel.taskListId = event.value;
    },
    
    notesChanged: function(event)
	{
        this._newmodel.notes = event.value;
    },
    
    updateButton: function(dueDateText)
	{
        var button = Mojo.View.render({
			object: 
			{
				text: dueDateText,
				buttonId: 'duedateButton'
			},
			template: "task/popupbutton"
		});
        this.dueDateElement.update(button);
    },
    
    onDueDateOtherTap: function(event)
	{
        var self = this;
        var dateMs = this.getCurrentDueDateMs();
        var dueDateText;
		
        self.controller.showDialog({
			template: 'datepicker/datepicker-scene',
			assistant: new DatePickerAssistant(
			{
				title: $L('Set due date'),
				sceneAssistant: this,
				defaultDate: dateMs ? new Date(dateMs) : undefined,
				callback: function(date)
				{
					// Here either a date (or null for no due date) is selected
					// and must be saved to the current record
					self.updated = true;
					if (date) 
					{
						self.dueDateChoice = 'custom';
						self._newmodel.dueDate = date.getTime();
						dueDateText = Mojo.Format.formatDate(date, { date: 'default' });
					}
					else 
					{
						self.dueDateChoice = 'none';
						self._newmodel.dueDate = null;
						dueDateText = $L('No due date');
					}
					self.updateButton(dueDateText);
				}
			})
		});
    },
    
    activate: function()
	{
		this.controller.document.addEventListener(Mojo.Event.deactivate, this._onSceneDeactivate);
    },
	
	deactivate: function()
	{
		this.controller.document.removeEventListener(Mojo.Event.deactivate, this._onSceneDeactivate);
	},
});
