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

var NoteAssistant = Class.create(
{
	$widget_noteText: 
	{
		attr: 
		{
            multiline: true,
			changeOnKeyPress: true,
			runTextLinker: true,
			focusMode: Mojo.Widget.focusAppendMode,
		},
		model: "noteTextModel",
	},
	$element_noteText: null,
	$element_memosNote: null,
	$element_memoShim: null,
	
	$widget_yellowCheckBox: { model: "checkBoxModel.yellow" },
	$widget_pinkCheckBox: { model: "checkBoxModel.pink" },
	$widget_greenCheckBox: { model: "checkBoxModel.green" },
	$widget_blueCheckBox: { model: "checkBoxModel.blue" },	

    initialize: function(data)
    {
        this.data = 
		{
			model: data.model,
			id: data.id,
			color: data.color,
			position: data.position,
			text: data.text
		};
		
		// Orginal note
		this.origNote =
		{
			text: null,
			color: null,
			position: null,
		};
		
		// Notes
        this.noteTextModel = 
		{
			value: '',
 			disabled: false,
			hintText: '',
		};
		
		// Colors
		this.checkBoxModel =
		{
			yellow: {},
			pink: {},
			green: {},
			blue: {}
		};
    },
    
    setup: function()
    {
		var self = this;
		var data = this.data;
		
		// Scene scroller
		this.controller.getSceneScroller().mojo.handleEdgeVisibility('bottom', true, this.$element_memoShim.clientHeight);
        
		// Set color early
		this.$element_memosNote.addClassName(data.color);
		
        if (data.id) 
        {
            // Load the note asynchronously
            this.data.model.loadNote(data.id, function(note)
            {
                self._onNoteLoaded(note, false);
            });
        }
        else 
        {
            this._onNoteLoaded.bind(this).defer(new Note(
            {
                text: data.text,
                color: data.color,
                position: data.position
            }), true);
        }
    },

    cleanup: function()
    {
		// We don't get a property change if the application is detroyed (rather than the scene just getting popped).
		// So, we get the current text value directly here.
		if (!this.isSaved && this.data.note) 
		{
			// Prevent note being saved twice. If we call cleanup twice (which can happen when going into card mode and then
			// closing the app) and the second time happens before the new note id has been returned, we will end up
			// saving two notes.
			this.isSaved = true;
			this.data.note.text = this.$widget_noteText.getValue();
			this._saveNote();
		}
    },
	
	$stageDeactivate_saveNote: function(event)
	{
		// When we go to card view, we cleanup (save) the current stage
		this.cleanup();
	},
	
	// Eat taps on the document that aren't on the tab, because we want to leave the textfield focused
	$tap_document: function(event)
	{
		this._enableDetails(false);
		for (var node = event.target; node; node = node.parentNode)
		{              
				if (node == this.$element_noteText)
				{
						return;
				}           
		}
		event.preventDefault();
	},

	$dragStart_memosDetails: function(event)
	{
		this.$tap_memosDetails(event);
	},
	
	$tap_memosDetails: function(event)
	{
		// If the text model is disabled, then the details will be enabled, so switch to text enabled/details disabled.
		// Or .. switch it the other way.
		this._enableDetails(!this.noteTextModel.disabled);
		Event.stop(event);
	},

    $propertyChange_noteText: function(event)
    {
        this.data.note.text = event.value;
    },
	
	$menu_palm_help_cmd: function(event)
	{
		new Mojo.Service.Request('palm://com.palm.applicationManager', 
		{
			method: 'open',
			parameters: 
			{
				id: 'com.palm.app.help',
				params:
				{
					target: 'http://help.palm.com/memos/index.html'
				}
			}
		});
	},
	
	$menu_email_memo_cmd: function(event)
	{
		new Mojo.Service.Request('palm://com.palm.applicationManager',
		{
			method: 'open',
			parameters:
			{
				id: 'com.palm.app.email',
				params:
				{
					summary: $L("Just a quick memo"),
					text: this._getHTMLNote()
				}
			}
		});
	},
	
	$menu_delete_memo_cmd: function(event)
	{
		var self = this;
		this.controller.showAlertDialog({
			message: $L("Are you sure you want to delete this memo?"),
			choices:
			[
				{label: $L("Delete"), value: "confirmed", type: "negative"},
				{label: $L("Cancel"), value: "nevermind", type: "dismiss"}
			],
			onChoose: function(value) 
			{
				if (value == "confirmed")
				{
					var id = self.data.note.id;
					if (id)
					{
						self.data.model.deleteNote(id);
					}
					self.deleted = true;
					self.controller.stageController.popScene();
				}
			}
		});
	},
	
	$propertyChange_checkboxes: function(event)
	{
        // Skip events that dont have a target id (we missed the box)
        if (!event.target.id) 
        {
            return;
        }
        
        var length = event.target.id.indexOf("CheckBox");
        if (length == -1) 
        {
            return;
        }
        
        // Here we don't care about the value but only about what was checked
        var newColor = event.target.id.substr(0, length);
        var oldColor = this.data.note.color;
        
        // Nothing to change?
        if (newColor == oldColor) 
        {
            // Put the old color back because we cannot tell the widget not to change it
            Foundations.Model.update(this, this.checkBoxModel[oldColor], { value: true });
            return;
        }
        
		var transition = this.controller.prepareTransition(Mojo.Transition.crossFade);
        this.$element_memosNote.removeClassName(oldColor);
        this.$element_memosNote.addClassName(newColor);
        
        Foundations.Model.update(this, this.checkBoxModel[oldColor], { value: false });
        Foundations.Model.update(this, this.checkBoxModel[newColor], { value: true });
        
		transition.run();
        
        this.data.note.color = newColor;
    },
    
    _onNoteLoaded: function(note, isnew)
    {
		Mojo.Log.info("onNoteLoaded: %j", note, isnew);
        this.data.note = note;
        
        for (var k in this.origNote) 
        {
            this.origNote[k] = isnew ? null : note[k];
        }
        
        // Track if note gets deleted
        this.deleted = false;
        
        this.$element_memosNote.addClassName(note.color);
        Foundations.Model.update(this, this.checkBoxModel[note.color], { value: true });
        
		Foundations.Model.update(this, this.noteTextModel, { hintText: $L('New memo...'), value: note.text || "" });
        // We need the cursor at the end, so blur and focus the field (which moves it)
		this.$widget_noteText.blur();
		this.$widget_noteText.focus();
    },

	_enableDetails: function(enable)
	{
		if (enable != this.noteTextModel.disabled) 
		{
			var transition = this.controller.prepareTransition(Mojo.Transition.crossFade);
			transition.run.bind(transition).defer();
			if (enable) 
			{
				this.$element_memosNote.addClassName('show-details');
				Foundations.Model.update(this, this.noteTextModel, { disabled: true });
				this.$widget_noteText.blur();
			}
			else 
			{
				this.$element_memosNote.removeClassName('show-details');
				Foundations.Model.update(this, this.noteTextModel, { disabled: false });
				this.$widget_noteText.focus();
			}
		}
	},
    
    _saveNote: function()
    {
        var note = this.data.note;
        
        // If note didnt change, we don't save it
        var changed = false;
        for (var k in this.origNote) 
        {
            if (note[k] != this.origNote[k]) 
            {
                changed = true;
                break;
            }
        }
        if (!changed) 
        {
			this.isSaved = false;
            return;
        }
        
        // SPECIAL CASE: If note is new and has no text, we dont save it regardless of any other changes
        if (this.origNote.text == null && note.text == "") 
        {
			this.isSaved = false;
            return;
        }
        // SPECIAL CASE: If note has been deleted, don't save it
        if (this.deleted) 
        {
			this.isSaved = false;
            return;
        }
		// SPECIAL CASE: If note is now empty we delete it
		if (note.text == "" || note.text == "\n")
		{
			var id = note.id;
            if (id) 
			{
                this.data.model.deleteNote(id);
				delete note.id;
				// We do *NOT* set the deleted flag (that is only set when we explicityly delete a note causing a pop)
            }
			this.isSaved = false;
			return;
		}
        
        var savenote = 
        {
            id: note.id
        };
        
        // Copy state changes into 'savenote'
        for (var k in this.origNote) 
        {
            if (this.origNote[k] != note[k]) 
            {
                savenote[k] = note[k];
            }
        }
        
        // Add modified stamp
        savenote.modifiedTimestamp = new Date().getTime();
        
        // Add a created stamp if we dont have one
        if (!note.createdTimestamp) 
        {
            savenote.createdTimestamp = savenote.modifiedTimestamp;
        }
		
		// Force font recalculation
		savenote.font = '';
        
        Mojo.log("Save note");
		var self = this;
        this.data.model.saveNote(savenote, function(id)
		{
			note.id = id;
			// One we know the note id, we can clear this flag so we can save the note again
			// If we dont clear the flag, we never save it again.  If we clear the flag before
			// we get the id, we save duplicates.
			self.isSaved = false;
		});
    },

	_getHTMLNote: function()
	{
		var val = this.$widget_noteText.getValue();
		// Convert newlines into <br/>
		val = val.replace(/\n/g, "<br/>");
		// Convert multiple spaces into &nbsp;...
		val = val.replace(/  /g, " &nbsp;");
		return val;
	}
});
