(function($){
////////////////////// BEGIN ////////////////////////////	
	
function __init__( el ){
  var div = $("<div>").addClass("input")

  var newEl = $(el).clone();
  $(el).replaceWith(div);
  div.append(newEl);

  Input.setup( newEl );
}	

var Input = {
  setup: function( el ){
    $(el).keydown( Keyboard.keydown );
  },
  
  measureText: function( text, el ){
    el = $(el);
    text = text.replace(" ", "&nbsp;")
    var span = $("<span/>")
                .append( text )
                .css({
                  "font-size": el.css("font-size"),
                  "font-family": el.css("font-family"),
                  "visibility": "hidden"
                })
                .css("visibility", "hidden")
    $("body").append( span );
    var width = span.width();
    span.remove();
    return width;
  },
  
  getAction: function( el ){
    var actions = $(el).parent().find(".bubble");
    
    if( actions.length > 0 ) return actions[0].innerHTML;
    return null;
  }
} 
	
var Keyboard = {
  keydown: function( event ){    
    switch(event.which){
      case 9:
        return Keyboard.keyTab(event);
      case 8:
        return Keyboard.keyDelete(event);
      case 32:
        return Keyboard.keySpace(event);
      case 13:
        return Keyboard.keyReturn(event);
      case 38:
        return Keyboard.keyUpArrow(event);
      case 40:
        return Keyboard.keyDownArrow(event);
      case 39:
        return Keyboard.keyRightArrow(event);
      case 37:
        return Keyboard.keyLeftArrow(event);
      default:
        Completer.remove();
        
    }
  },
  
  keyTab: function( event ){
    Completer.remove();        
    
    var el = $(event.currentTarget);
    
    if( !Input.getAction(el) ) Results.completeAction( el );
    event.preventDefault();
    
  },
  
  keyDelete: function( event ) {
    Completer.remove();    
    
    var el = $(event.currentTarget);
    var cursorPos = el[0].selectionStart;    
    var bubbles = el.parent().find(".bubble");

    if( cursorPos == 0 && bubbles ){
      $(bubbles[ bubbles.length-1 ]).remove();
      $(".ac_results").css({opacity: 1});
    }
  },
  
  keyReturn: function( event ) {
    var action = Input.getAction( event.currentTarget );
    if( action ) Preview.execute();
  },
  
  keySpace: function( event ) {
    var el = $(event.currentTarget);
    var action = Input.getAction(el);
    
    switch(action){
      case "translate":
        //Completer.make( "from | to", el );
        break;
      case null:
        if( Results.completeAction( el ) )
          event.preventDefault();
        break;
    }
  },
  
  keyDownArrow: function( event ) {
    var taskfox = $("iframe")[0].contentWindow.TaskFox;
    if( taskfox ) taskfox.Keys.map.downArrow();
  },
  
  keyUpArrow: function( event ) {
    var taskfox = $("iframe")[0].contentWindow.TaskFox;
    if( taskfox ) taskfox.Keys.map.upArrow();
  },
  
  keyRightArrow: function( event ) {
    var taskfox = $("iframe")[0].contentWindow.TaskFox;
    if( taskfox ) taskfox.Keys.map.rightArrow();
    event.preventDefault();
  },
  
  keyLeftArrow: function( event ) {
    var taskfox = $("iframe")[0].contentWindow.TaskFox;
    if( taskfox ) taskfox.Keys.map.leftArrow();
    
    event.preventDefault();
  }  
}	


var Completer = {
  make: function( what, el ){
    var width = Input.measureText( el.attr("value"), el );
  
    var options = $(".options")[0] || $("<div>").text( what ).addClass("options")[0];
    options = $(options);
    
    options.click(function(){
      Bubble.add("from", el);
    });
  
    $("body").append(options);
    options.css({
      position: "absolute",
      left: el.position().left + width,
      top: el.position().top + el.height() + 5
    });
  },
  
  remove: function(){
    $(".options").remove();
  }
}	
	
var Bubble = {
  _create: function( text ){
    return $("<div>").addClass( "bubble" ).text( text );
  },
  
  add: function( text, el ){
    var el = $(el);
    var bubble = Bubble._create( text );
    el.before( bubble );
  }
}	

window.Results = {
  onSelect: function(el, input){
    var text = $(el).text();
    
    if( text.match(/\.{3}/) ){
      text = text.slice(0, text.length-3);
      Bubble.add( text, input );
      return false;      
    }
    
    return true;
  },
  
  completeAction: function(el){
    var actions = $(".ac_results li").filter(function(){return this.innerHTML.match(/\.{3}/)})
    if( actions.length > 0 ){
      var action = actions[0].innerHTML;
      action = action.slice( 0, action.length-3 );
      Bubble.add( action, el );
      el.attr("value", "");
      $(".ac_results").hide();
      return true;
    }
    return false;
  }
  
}

var Preview = {
  show: function( url ){
    $(".preview").show()
    $(".preview>iframe").show().attr("src", url);
    $(".preview>span").hide();
  },
  
  hide: function(){
    $(".preview").hide();
    $(".preview iframe").attr("src", "#").hide();
    $(".preview>span").show();
  },
  
  update: function( input ){    
    var updatePreview = $(".preview iframe")[0].contentWindow.updatePreview
    if( updatePreview ) updatePreview( input );
  },
  
  execute: function( ){
    input = $("#taskfox").val();
    var run = $(".preview iframe")[0].contentWindow.execute
    if( run ) run( input );
  }
}

window.Preview = Preview;

var Storage = {};

var Invariants = {
  preview: function(){
    var action = Input.getAction( $("#taskfox") );
    if( action ){
      if( $(".preview:visible").length > 0 ) return;
      
      switch( action ){
        case "search":
          Preview.show( "commands/google.html" );
          break;
        case "google":
          Preview.show( "commands/google.html" );
          break;
        case "twitter":
          Preview.show( "commands/twitter.html" );
          break;
        case "video search":
          Preview.show( "commands/video.html");
          break;
        case "translate":
          Preview.show( "commands/translate.html");
          break;
        case "track flight":
          Preview.show( "commands/track-flight.html" );
          break;
        case "wikipedia":
          Preview.show( "commands/wikipedia.html" );
          break;
        case "calculate":
          Preview.show( "commands/calculate.html" );
        default:
          $(".preview").show();
          break;
      }
      
    }
    else Preview.hide();
  },
  
  previewUpdater: function(){
    var action = Input.getAction( $("#taskfox") );
    var input = $("#taskfox").val();
    
    if( Storage.input == input || input == "") return;    
    
    Storage.input = input;
    Preview.update( input );

  },
  
  autocomplete: function(){
    var action = Input.getAction( $("#taskfox") );
    if( action ){
      $(".ac_results").css({opacity: 0});
    }
  }
}

var timer = setInterval(function(){
  for each (func in Invariants){
    func();
  }
}, 200);
	
	
jQuery.fn.bubble = function(){
	return this.each(function(){
		__init__(this);
	});
}
	
	
////////////////////// END ////////////////////////////	
})(jQuery);





