 var Screenplay = Class.create({
  initialize:function(characters, easyMode, sandboxMode, startSandbox) {
    this.initAutoComplete(characters);
    //this.initSortable();
    this.unsaved = false;
    this.easyMode = (easyMode==1) ? true : false;
    this.sandboxMode=(sandboxMode==1) ? true : false
    this.registerEvents();
    this.dropdown=null;
    this.scenes = new Scenes();
    this.helper = new ScreenplayHelper();
    if (startSandbox==1) this.startSandbox();
    this.rev_cache=[];
  },

  registerEvents: function() {
    Event.observe(document,'keydown',this.keyDownListener.bind(this));
    Event.observe(document,'keyup',this.setKeyInstructions.bind(this));
    Event.observe('screenplay','click',this.clickListener.bind(this));
    Event.observe('screenplay','mousedown',this.mouseDownListener.bind(this));
    Event.observe('screenplay','mouseup',function(event){Event.stop(event)});
    if ($('save_button')) Event.observe('save_button','click',this.saveButtonListener.bind(this));
    if ($('add_new_scene_button')) Event.observe('add_new_scene_button','click',this.addSceneButtonListener.bind(this));
    if ($('preferences_button')) Event.observe('preferences_button','click',this.show_preferences.bind(this));
    if ($('refresh_button')) Event.observe('refresh_button','click',this.refreshButtonListener.bind(this));
    if ($('help_button')) Event.observe('help_button','click',this.helpButtonListener.bind(this));
    if ($('element_selector')) Event.observe('element_selector','change',this.elementSelectorListener.bind(this));
    if ($('scene_selector')) Event.observe('scene_selector','change',this.sceneSelectorListener.bind(this));
    if (this.sandboxMode) {
      if ($('reset_button')) Event.observe('reset_button','click',this.resetButtonListener.bind(this));
      if ($('convert_button')) Event.observe('convert_button','click',this.convertButtonListener.bind(this));
    }
    window.onbeforeunload = function(){
     if (this.unsaved) {
       return "Click the save button (disk icon) in the upper left to save your work before leaving."
     }
    }.bind(this)

    if(this.easyMode) {
      Event.observe('resource_element_buttons','mousedown',this.handleEasyMode.bind(this));
    }

  },

  handleEasyMode: function(event) {
    var button = Event.findElement(event,'input');
    if(!button) return;
    switch (button.id) {
      case "cancel_element":
        this.viewNode(this.editableContainer);
        break;
      case "submit_element":
        if(this.unsaved) {
          this.saveElement(this.editableContainer);
        }
        this.viewNode(this.editableContainer);
        break;
      case "delete_element":
        this.removeButtons(this.editableContainer);
        this.deleteElement(this.editableContainer);
        break;
      case "choose_slugline":
        this.switchToSlugline();
        Event.stop(event);
        break;
      case "choose_action":
        this.switchToAction();
        Event.stop(event);
        break;
      case "choose_dialogue":
        this.switchToDialog();
        Event.stop(event);
        break;
    }
  },

  initAutoComplete: function(characters) {
    this.characterCompleter = new Autocomplete(null,characters, {onSelect:function() { this.autoCompleteSelect(); }.bind(this) });
  },

  initSortable: function() {
    Sortable.destroy('')
    Sortable.create('',{
      tag:'div',
      handle:'handle',
      onUpdate:function(el){pb_debug('SORT ORDER CHANGED',el)}
    })
  },

  saveButtonListener:function() {
    this.saveElement(this.editableContainer);
    this.viewNode(this.editableContainer);
  },

  startSandbox:function() {
    this.editNode($('screenplay').down('div.scene').down('div.element_container').down('div.body').down('div'));
    this.unsaved = true;
    this.helpButtonListener();
  },

  refreshButtonListener:function() {
   this.helper.refresh_page();
  },

  convertButtonListener:function() {
    this.helper.go_to_url(this.paths.convert);
  },

  resetButtonListener:function() {
    this.helper.go_to_url(this.paths.reset);
  },

  addSceneButtonListener:function() {
    this.scenes.scene_details();
  },

  helpButtonListener:function() {
    this.dropdown=new Panel({
     content:$('resource_help').innerHTML ,
     panelClass:'help_popup',
     displayOverlay:true,
     loadingText:'&nbsp;',
     enableClickOut:true
   }).open();
  },

  clickListener: function(event) {
   var link = Event.findElement(event,'a');
   if(!link) return;
   switch (link.className) {
    case 'show_revs':
     this.toggleRevs(link,true);
     break;
    case 'hide_revs':
     this.toggleRevs(link,false);
     break;
    case 'toggle_screenplay_comments':
     this.toggleComments(link);
     break;
    case 'toggle_scene_details':
     this.scene_details(link);
     break;
    case 'branch_details':
     this.branch_scene(link);
     break;
    case 'lock_scene':
     this.lock_scene(link, true);
     break;
    case 'unlock_scene':
     this.lock_scene(link, false);
     break;
    case 'branch_scene':
     this.branch_scene(link, true);
     break;
    case 'start_writing':
     this.insertFirstEditableArea(link)
     break;
    case 'restore_element':
     this.restoreElement(link);
     break;
    case 'revert_element':
     this.revertElement(link);
     break;
   }
  },

  mouseDownListener:function(event) {
    if(this.characterCompleter.active) return;
    if(Event.element(event).up('#screenplay_end')) { this.insertLastEditableArea(); return; }
    if(Event.findElement(event,'textarea')) return;
    if(this.editableContainer) this.leaveContainer(this.editableContainer); //Has to be after check-for-clicking-on-textarea for character/dialogue toggle.
    if(Event.element(event).up('#resource_element_buttons'))  { return; }
    if(Event.findElement(event,'p')) {
      var container = Event.findElement(event,'div');
      if(!container || container == $('screenplay') || container.getAttribute('locked')==1) return;
      this.editNode(container);
    } else {
      if (this.editableContainer) this.viewNode(this.editableContainer);
    }
    Event.stop(event);
  },

  editNode:function(container) {
    if(this.editableContainer && this.editableContainer !=container) this.leaveContainer(this.editableContainer); //If we used to be editing a different container, checkout what's going on there.
    try {
      if (container.down('p').up('div').getAttribute("locked")=="1") return; //Can't edit locked elements.
    } catch (e) {
      //Don't worry about it.
    }
    this.editableContainer = container;
    container.select('p').each(function(p,i) {
      var replace_with = this.helper.clean_string(p.innerHTML);
      if (p.className=="character") replace_with = replace_with.replace("(CONT&#39;D)",""); //gsub uses regex, which breaks on the ()
      var ta = new Element('textarea',{'class':p.className});
      ta.value=replace_with;
      p.insert({after:ta});
      ta.setStyle({width:p.getWidth()-2+'px',height:p.getHeight()-4+'px'});
      ta.setStyle({height:ta.scrollHeight})
      this.adjustTextAreaHeight(ta);
      p.remove();
    }.bind(this));

    new_ta = container.down('textarea');
    if(new_ta.hasClassName('character')) {
      this.setAutoComplete(new_ta);
    }
    new_ta.focus();

    if(this.easyMode) {
      this.addButtons(container); //For transition mode, where we show buttons to the user.
    }
    this.setElementSelector(container.className);
    this.setKeyInstructions(container);
    this.enableTextButtons(true);
  },

  addButtons:function(container) {
    container.up('.element_container').down('.body').insert($('resource_element_buttons').show())
    container.up('div.body').addClassName("easy_edit");
  },
  removeButtons:function(container) {
    try {
      container.up('div.body').removeClassName("easy_edit");
      $('resource_divs').insert($('resource_element_buttons').hide());
    } catch (e) {
      //Couldn't remove buttons (happens in start case)
    }
  },

  enableTextButtons:function(s) {
   if ($('bold_button')) $('bold_button').disabled=!s;
   if ($('italic_button')) a$('italic_button').disabled=!s;
   if ($('underline_button')) $('underline_button').disabled=!s;
  },

  setAutoComplete: function(ta) {
    this.currentAutoComplete = ta;
    this.autocompleteFocusListener = function(){this.characterCompleter.moveToElement(ta)}.bind(this)
    Event.observe(ta,'focus',this.autocompleteFocusListener);
  },
  unsetAutoComplete: function() {
    Event.stopObserving(this.currentAutoComplete,'focus',this.autocompleteFocusListener);
    this.currentAutoComplete = null;
  },
  autoCompleteSelect:function() {
    if (this.currentAutoComplete) this.currentAutoComplete.focus()
  },

  viewNode:function(container) {
    container.select('textarea').each(function(ta,i) {
      var p = new Element('p',{'class':ta.className}).update($F(ta));
      ta.insert({after:p});
      ta.remove();
    });

    container.select('div.element_buttons').each(function(b,i) { b.remove(); } )
    this.editableContainer = null;
    this.disableElementSelector();
    this.enableTextButtons(false);
    this.clearKeyInstructions();
    if(this.currentAutoComplete) this.unsetAutoComplete();

    if(this.easyMode) {
      this.removeButtons(container);
    }
  },

  adjustTextAreaHeight: function(ta) {
    if (ta.scrollHeight > ta.clientHeight && !window.opera) ta.style.height = (ta.scrollHeight) + 'px';
  },

  keyDownListener:function(event) {
    var textarea = Event.findElement(event,'textarea');
    var container = this.editableContainer;
    if(!textarea || !container) return;
    var inputs = container.select('textarea');
    var is_blank = this.isContainerEmpty(container);

    if(this.characterCompleter.active) return;

    this.adjustTextAreaHeight(textarea);

    switch(event.keyCode) {
      case Event.KEY_BACKSPACE:
        if(textarea == inputs[0] && is_blank) {
          Event.stop(event);
          this.unsaved = false;
          this.focusPreviousInput(textarea);
          //this.deleteElement(container); //Deletion is handled when you leave an empty element.
        } else if($F(textarea).blank()) {
          this.setUnsaved();
          this.focusPreviousInput(textarea);
        } else {
          this.setUnsaved();
        }
        break;
      case Event.KEY_DELETE:
        if(is_blank) {
          this.unsaved = false;
          this.focusNextInput(textarea);
          this.deleteElement(container);
        } else {
          this.setUnsaved();
        }
        break;
      case Event.KEY_RETURN:
        if (container.className=="dialog_element" && $F(textarea).strip().endsWith(")")) { Event.stop(event); return; }
        if(textarea == inputs.last()) {
          if(is_blank) {
            this.switchToSlugline();
          } else {
            this.saveElement(container);
            this.newElement();
          }
        } else {
          var next_ta = textarea.next('textarea')
          next_ta.focus();
          this.setCaretPosition(next_ta,0);
        }
        Event.stop(event);
        break;
      case Event.KEY_TAB:
        if(textarea == inputs.last()) {
          if (!textarea.value.blank() && this.getCaretPosition(textarea)==textarea.value.length) { //if tabbing at the end of an existing field, treat as if itwere a return.
            this.saveElement(container);
            this.newElement();
          } else {
            this.setUnsaved();
            this.switchElementType();
          }
        } else {
          this.focusNextInput(textarea);
        }
        Event.stop(event)
        break;
      case Event.KEY_UP:
       //if (container.className=="dialog_element" && $F(textarea).strip().endsWith(")")) { textarea.replace($F(textarea)) } //Should insert newline at caret.
       if(this.isFirstRow(textarea)) {
          this.focusPreviousInput(textarea);
          Event.stop(event);
        }
        break;
      case Event.KEY_DOWN:
        if(this.isLastRow(textarea)){
          this.focusNextInput(textarea);
          Event.stop(event);
        }
        break;
      case Event.KEY_LEFT:
      case Event.KEY_RIGHT:
        break;
      case Event.KEY_ESC:
        this.leaveContainer(container)
        Event.stop(event)
        break;
      default:
        this.setUnsaved();
    }
  },

  isContainerEmpty:function(container) {
    var inputs = container.select('textarea');
    return !inputs.any(function(i){return !$F(i).blank()});
  },

  leaveContainer:function(container) {
    if(this.isContainerEmpty(container)) {
      this.deleteElement(container);
    } else {
      this.saveElement(container);
    }
    this.viewNode(container);
  },

  focusPreviousInput: function(textarea) {
    try {
      var prev_ta = textarea.previous('textarea');
      if(prev_ta) { //If we're doing dialogue
        prev_ta.focus();
      } else {
        this.saveElement(this.editableContainer);
        var prev_element = textarea.up('div.element_container').previous('div.element_container').down('div.body').down('div');
        if(prev_element) {
          this.editNode(prev_element);
          previous_ta = prev_element.select('textarea').last();
          if (previous_ta) previous_ta.focus();
          this.setCaretPosition(previous_ta,$F(previous_ta).length)
        }
      }
    } catch (e) {
      //Couldn't find previous focus.
      this.leaveContainer(this.editableContainer);
    }
    return
  },

  focusNextInput: function(textarea) {
    var next_ta = textarea.next('textarea');
    if(next_ta) {
      next_ta.focus();
    } else {
      this.saveElement(this.editableContainer);
      var next_element = textarea.up('div.element_container').next('div.element_container').down('div.body').down('div');
      if(next_element) {
        this.editNode(next_element);
        var next_ta = next_element.down('textarea');
        next_ta.focus();
        this.setCaretPosition(next_ta,0);
      }
    }
    return
  },

  newElement:function() {
    if(!this.editableContainer) return;
    this.buildNewElement(this.editableContainer, true);
  },

  insertFirstEditableArea:function(start_link) { //Scene is the 'main' class
   var starting_showdown = (start_link.getAttribute("showdown")=="1")
   var next_element_type = (starting_showdown) ? "action" : "slugline";
   if (starting_showdown) {
    var insert_after=start_link.up('div.main').select('div.element_container').last().down("div.body").down("div");
    start_link.up('div.unwritten_scene').remove();
   } else {
    var insert_after = start_link.up("div.main");
    insert_after.down('div.body').remove();
    insert_after.down('div.right').remove();

   }
   this.buildNewElement(insert_after, true, next_element_type, true);
  },

  insertLastEditableArea:function() {
    try {
      var scene = $('screenplay').select('div.scene').last().select('div.element_container').last().down('div.body').down('div'); //WOWZ!
    } catch (e) {
      pb_debug("couldn't find the last element")
    }

    if (scene) this.buildNewElement(scene, true, "action", true);
  },

  buildNewElement:function(after, create_with_focus, force_type, last_element) {
    var container = new Element('div',{'class':'element_container'})
    if (e=after.up('div.element_container')) {
     e.insert({after:container});
    } else {
     after.insert(container)
    }
    var container_body = new Element('div',{'class':'body'});
    var container_details = new Element('div',{'class':'right'});
    container.insert(container_body);
    container.insert(container_details);
    var type = container.className;
    this.viewNode(after);
    var new_container;
    if (force_type) {
     switch (force_type) {
      case "slugline": new_container=this.newSlugline(); break;
      case "action": new_container=this.newAction(); break;
      case "dialog": new_container=this.newDialog(); break;
     }
    } else {
     switch(type) {
       case "dialog_element":
         new_container = this.newDialog()
         break;
       case "slugline_element":
       case "action_element":
       default:
        new_container = this.newAction()
        break;
     }
    }
    container_body.insert(new_container);
    new_container.setAttribute("new","true");
    new_container.setAttribute("scene", after.getAttribute("scene"));
    new_container.setAttribute("map", after.getAttribute("map")); //Should be passed to screenplay object elsewhere.
    new_container.setAttribute("after", after.getAttribute("id"));
    if (last_element || after.up("div.scene").select("div.element_container").last()==container) new_container.setAttribute("append",1); //If we're the last element in the map.
    if (create_with_focus) {
     this.editNode(new_container);
    } else {
     this.viewNode(new_container);
     new_container.select('p').last().update('&nbsp;');
    }
  },

  newDialog:function() {
   var new_container = new Element('div',{'class':'dialog_element'});
   var new_character_ta = new Element('textarea',{'class':'character'});
   var new_dialog_ta = new Element('textarea')
   new_container
     .insert(new_character_ta)
     .insert(new_dialog_ta);
   this.setAutoComplete(new_character_ta);
   setTimeout(function(){new_character_ta.focus();},100);
   return new_container;
  },

  newAction:function() {
    var new_container = new Element('div',{'class':'action_element'});
    var new_action_ta = new Element('textarea');
    new_container.insert(new_action_ta);
    setTimeout(function(){new_action_ta.focus();},100);
    return new_container;
  },

  newSlugline:function() {
    var new_container = new Element('div',{'class':'slugline_element'});
    var new_action_ta = new Element('textarea');
    new_container.insert(new_action_ta);
    setTimeout(function(){new_action_ta.focus();},100);
    return new_container;
  },

  switchElementType:function() {
    var type = this.editableContainer.className;
    switch(type) {
      case "action_element":
        this.switchToDialog();
        break;
      case "dialog_element":
      case "slugline_element":
        this.switchToAction();
        break;
    }
  },

  sceneSelectorListener:function() {
    var scene = $F('scene_selector');
    if (!scene) return;
    window.location=this.paths['screenplay'] + "?_s=" + scene;
  },

  elementSelectorListener:function() {
    if(!this.editableContainer) return;
    var value = $F('element_selector');
    switch (value) {
      case "action_element"     : this.switchTo(200);break;
      case "dialog_element"     : this.switchTo(300);break;
      case "slugline_element"   : this.switchTo(100);break;
      case "transition_element" : this.switchTo(400); break;
      case "shot_element"       : this.switchTo(500); break;
    }
    this.setUnsaved();
  },

  setElementSelector:function(value) {
    if (!$('element_selector')) { return; } //Not visible for logged out users.
    $('element_selector').disabled = false;
    var option = $A($('element_selector').options).find(function(opt){return (opt.value == value)})
    if(option) option.selected = true;
  },

  disableElementSelector: function() {
    $('element_selector').disabled = true;
  },

  isFirstRow: function(ta) {
    return (Math.floor(this.getCaretPosition(ta)/(ta.clientWidth/8))==0);
  },

  isLastRow: function(ta) {
    var ri = Math.floor(this.getCaretPosition(ta)/(ta.clientWidth/8));
    return (ri==Math.floor($F(ta).length/(ta.clientWidth/8)));
  },

  switchTo:function(type) {
   var inputs = this.editableContainer.select('textarea');
   this.editableContainer.className = this.classNameFromType(type);
   inputs[0].className = (type==300) ? "character" : "";
   inputs[0].setStyle({width:''});
   if (type==300) {
    if(!inputs[1]) this.editableContainer.insert(new Element('textarea'));
   } else {
    if(inputs[1]) {
      inputs[0].insert(" " + $F(inputs[1]));
      inputs[1].remove();
    }
   }
   inputs[0].blur()
   this.editNode(this.editableContainer);
   inputs[0].focus()
  },

  switchToDialog:function() {
    this.switchTo(300);
  },
  switchToAction:function() {
    this.switchTo(200);
  },
  switchToSlugline:function() {
    this.switchTo(100);
  },
  switchToTransition:function() {
    this.switchTo(400);
  },
  switchToShot:function() {
   this.switchTo(500);
  },

  setKeyInstructions: function() {
    if (!$('key_instructions')) { return; }
    if(!this.editableContainer) return;
    var type = this.editableContainer.className;
    var instructions = {tab:'',enter:''};
    switch (type) {
      case "action_element"   : instructions = {tab:"Dialog",enter:"Action"};break;
      case "dialog_element"   : instructions = {tab:"Action",enter:"Dialog"};break;
      case "slugline_element" : instructions = {tab:"Action",enter:"Action"};break;
    }
    var inputs = this.editableContainer.select('textarea');
    if(!inputs.any(function(i){return !$F(i).blank()})) {
      instructions.enter = "Slugline";
    }
    $('key_instructions').update("<b>[TAB]:</b> " + instructions.tab + ", <b>[ENTER]:</b> " +  instructions.enter);
  },

  clearKeyInstructions: function() {
    if (!$('key_instructions')) { return; }
    $('key_instructions').update();
  },

  setUnsaved: function() {
    this.unsaved = true;
    $('save_button').disabled = false;
  },

  setSaved: function() {
    this.unsaved = false;
    $('save_button').disabled = true;
  },

  saveElement:function(container) {
    if(!this.unsaved) return;
    var text = container.select('textarea').collect(function(ta){return $F(ta)});
    container.setAttribute("type", this.getElementType(container));
    /*
    pb_debug("text length:" + text[0].length + "||" + text[0].indexOf('\n'))
    if (text[0].indexOf('\n') !=-1 || text[0].length > 1500) {
      this.prompt_import();
    }
    */
    saver.save_element(container);//WTF
    this.setSaved();

  },

  deleteElement:function(container) {
    if (!container) { return; }
    if (container.hasClassName("element_container")) {
     element_to_delete = container.down('div.body').down('div');
     container.remove();
     container = element_to_delete;
    } else {
     if (e=container.up('div.body').up('div.element_container')) {
      e.remove();
     } else {
      pb_debug("couldn't remove div") //TODO: fix this scenario
     }
    }

    if(container.getAttribute('new') != "true") {
      saver.delete_element(container);
    } else {
      //the element was never saved, so don't worry about it
    }

    this.setSaved();
  },

  getElementType:function(container) {
    if(!container) return;
    var type = container.className;
    switch (type) {
      case "action_element"     : return 200; break;
      case "dialog_element"     : return 300; break;
      case "slugline_element"   : return 100; break;
      case "transition_element" : return 400; break;
      case "shot_element"       : return 500; break;
    }
    return;
  },
  classNameFromType:function(type) {
    if(!type) return;
    switch (type) {
      case 200  : return "action_element"; break;
      case 300  : return "dialog_element"; break;
      case 100  : return "slugline_element"; break;
      case 400  : return "transition_element" ; break;
      case 500  : return "shot_element"; break;
    }
    return;
  },

  getCaretPosition: function(ta) {
    var CaretPos = 0; // IE Support
    if (document.selection) {
      ta.focus ();
    var Sel = document.selection.createRange ();
    Sel.moveStart ('character', -ta.value.length);
    CaretPos = Sel.text.length;
    } else if (ta.selectionStart || ta.selectionStart == '0') {
    CaretPos = ta.selectionStart;
    }
    return (CaretPos);
  },

  setCaretPosition: function(ta, pos){
    if(ta.setSelectionRange) {
    ta.focus();
      ta.setSelectionRange(pos,pos);
    } else if (ta.createTextRange) {
    var range = ta.createTextRange();
    range.collapse(true);
    range.moveEnd('character', pos);
    range.moveStart('character', pos);
    range.select();
    }
  },

  set_num_pages:function(num_pages) { //This should update as user writes screenplay
   if ($('total_pages')) $('total_pages').replace(num_pages);
  },
  set_current_page:function(num) {
   var n = (this.base_page + num)
   $('current_page').value=(n==0) ? 1 : n;
  },
  set_scenes:function(scenes) {

   if (!$('scene_selector')) return;

   $('scene_selector').select('option').each(function(o) { o.remove(); });
   for (scene in scenes) {
    s = scenes[scene];
    option = new Element('option', {'value':s.sceneID}).update(s.title + " (" + s.numPages + " pgs)");
    if (s.isCurrentScene==1) { option.selected=true; this.base_page = s.startPage; this.set_current_page(0); }
    $('scene_selector').insert(option);
   }
   $('scene_selector').insert(new Element('option', {'value':'all'}).update("Show all"));
   $('scene_selector').disabled=false;
  },
  set_paths:function(p) {
   this.paths = p;
   this.scenes.paths=p;
  },
  set_insertables:function(){
   $('screenplay').select('div.scene').each(function(scene,i) { this.buildNewElement(scene.select('div.body div').last(), false); }.bind(this) )
  },
  branch_scene:function(scene) {
    var scene_id = scene.getAttribute('scene')
    if (scene_id) this.scenes.branch_scene(scene_id);
  },
  scene_details:function(scene) {
    this.scenes.scene_details(scene);
  },
  show_preferences:function() {
     this.dropdown=new Panel({
       url:this.paths['preferences'] ,
       panelClass:'preferences',
       displayOverlay:true,
       loadingText:'&nbsp;',
       enableClickOut:true
     }).open();
  },

  revertElement:function(link) { //Link is the <a> clicked on
    var container = link.up('div.element_container').down('div.body').down('div');
    var element = container.getAttribute('id');
    var map = container.getAttribute('map');
    var scene = container.getAttribute('scene');
    var rev = container.getAttribute('rev');
    saver.revert_element(map,scene,element,rev, container);
  },

  restoreElement:function(link) { //Link is the <a> clicked on
    var container = link.up('div.element_container').down('div.body').down('div');
    var element = container.getAttribute('id');
    var map = container.getAttribute('map');
    var scene = container.getAttribute('scene');
    var rev = container.getAttribute('rev');
    saver.restore_element(map,scene,element,rev, container);
  },

  toggleRevs:function(e, s) {
   if (s) {
     var container = e.up('div.right');
     var scene = container.getAttribute('sceneID');
     var map = container.getAttribute('mapID');
     var element = container.getAttribute('elementID');
     this.rev_cache[element]=e.up('div.element_container').innerHTML;
     saver.load_revs(scene, map, element, e.up('div.element_container'));
   } else {
    var element = e.getAttribute('element');
    e.up('div.element_container').up('div.element_container').update(this.rev_cache[element]);
   }
  },

  toggleComments:function(e) {
   var container = e.up('div.right');
   if (e=container.down('div.comments_container')) {
    e.replace('');
    return;
   }
   var collection_id = container.getAttribute('collectionID');
   var comments_container = new Element('div', {'class':'comments_container'})
   container.insert(comments_container);
   saver.load_comments(collection_id, comments_container);
  },

  show_comments:function(container, comments_html) {
   container.insert(comments_html);
  },

  show_revs:function(container, revs) {
   var active_element = container.down('p').up('div'); //TODO: This needs to be more flexible.
   var element_id = active_element.getAttribute('id');
   container.update('');
   revs.revs.each(function(rev) { container.insert(rev); }.bind(this));
   var button_str = "<center><a href='javascript://' class='hide_revs' element='" + element_id + "' ><span class='pretend_link'>Hide Previous Versions</span></a></center>"
   var close_button = new Element('div', {'class':'rev_close'}).update(button_str);
   container.select('div.element_container').last().down('div.body').insert(close_button);
  },

  prompt_import:function() {
    //Coming in a bit.
  }
})

 var ScreenplayHelper = Class.create({
  initialize:function() {
  //No empty functions?
  },
  clean_string:function(s) {
   if (typeof(s)=="string" && s !='' && s !=undefined) {
    ns=s.strip().replace(/\r|\n|\r\n/g,"");
    cs=ns.replace(/(<span>)|(<\/span>)/gmi, "\r");
    ds = cs.replace(/<BR>/g, "<br>")
    //bs=cs.replace(/\'/g,"&#39;");
    return ds.gsub("  ", " ");
 } else {
  return s;
   }
  },
  throw_error:function(e) {
   var default_msg = "We had an error with your last request. Please refresh the page.";
   var error_msg = "<div class='wrapper'><h2>Oops! Something went wrong.</h2>";
   error_msg+="<h4>" + default_msg + "</h4>";
   if(e.msg) { error_msg+="<h4 class='error'>" + e.msg + "</h4>"; }
   error_msg+="<div style='width:100%;text-align:center;margin:auto;'><div class='simple_buttons' style='width:50px;margin:auto;'><a href='javascript://' class='panel_action' rel='close'>OK</a></div><br clear='all'/></div>";
   error_msg+="</div>";
   this.error=new Panel({
       content:error_msg,
       panelClass:'error_popup',
       displayOverlay:true,
       loadingText:'&nbsp;',
       enableClickOut:true,
       onClose:function(){ this.refresh_page(); }.bind(this)
     }).open();
  },
  show_loading:function(s) {
   if (s) { $('loading_animation').show(); } else { $('loading_animation').hide(); }
  },
  notify:function(s) {
    if ($('flash_notification')) {
      $('flash_notification').update(s);
      $('flash_notification').show();
      $('flash_notification').fade({ delay:2, duration: 1.0, from: 1, to: 0 });
    }
  },
  lightbox_notify:function(s) {
    if ($('lightbox_notification')) {
      $('lightbox_notification').update(s);
      $('lightbox_notification').show();
      $('lightbox_notification').fade({ delay:2, duration: 1.0, from: 1, to: 0 });
    }
  },
  go_to_url:function(u) {
   window.location =u;
  },
  refresh_page:function() {
    this.go_to_url(window.location.href)
  }
})

 var Outline = Class.create({
  initialize:function(characters) {
    this.unsaved = false;
    this.registerEvents();
    this.helper = new ScreenplayHelper();
    this.setButtons();
  },

  registerEvents: function() {
    if ($('save_button')) Event.observe('save_button','click',this.saveButtonListener.bind(this));
    if ($('save_draft_button')) Event.observe('save_draft_button','click',this.saveButtonListener.bind(this));
    if ($('edit_button')) Event.observe('edit_button','click',this.editButtonListener.bind(this));

    Event.observe(document,'keydown',this.keyDownListener.bind(this));
    Event.observe('outline','mousedown',this.clickListener.bind(this));
    Event.observe('outline','mouseup',function(event){Event.stop(event)});
  },

  clickListener:function(event) {

    if(Event.findElement(event,'textarea')) return;
    if (e=Event.findElement(event, 'div.save_controls')) return;
    if(Event.findElement(event,'p')) {
      var container = Event.findElement(event,'div');
      if(!container || container == $('screenplay') || container.getAttribute('locked')==1) return;
      this.editOutline(container);
    } else {
      if (this.editing) this.stopEditing(true);
    }
    Event.stop(event);
  },

  keyDownListener:function(event) {
    var textarea = Event.findElement(event,'textarea');
    if(!textarea) return;
    this.adjustTextAreaHeight(textarea);
  },

  setButtons:function() {
   if ($('save_button')) $('save_button').disabled=!(this.editing);
   if ($('save_draft_button')) $('save_draft_button').disabled=!(this.editing);
   if ($('edit_button')) $('edit_button').disabled=(this.editing);
  },

  saveButtonListener:function() {
    this.save();
  },

  editButtonListener:function() {
    this.editOutline($('outline').down('div.body'));
  },

  editOutline:function(container) {

   var outline = container.select('p').first();
   if (!outline || outline.getAttribute('locked')==1) return;
   this.editing=true;
   this.setButtons();
   var ta = new Element('textarea');

   if (outline.getAttribute('revID') !=0) {
    ta.value=this.helper.clean_string(outline.innerHTML).gsub('<br>', '\n');
   }

   ta.setStyle({width:outline.getWidth()-2+'px',height:outline.getHeight()+'px'});

   if(ta.getHeight() < 100) ta.setStyle({height:'100px'});
   ta.setAttribute('revID', outline.getAttribute('revID'));
   outline.insert({after:ta});
   ta.setStyle({height:ta.scrollHeight})
   this.adjustTextAreaHeight(ta);
   outline.remove();

   $('save_controls').show();
   this.outline_ta = container.select('textarea').first();
   this.outline_ta.focus();
  },

  stopEditing:function(restore) {
   if (!this.outline_ta) return;
   var p = new Element('p').update("&nbsp;");
   p.setStyle("height", this.outline_ta.getHeight());
   this.outline_ta.insert({after:p});
   this.outline_ta.remove();
   this.outline_ta=null;
   this.editing=false;
   this.setButtons();
   if (restore) this.get();
    $('save_controls').hide();
  },
  save:function() {
   var projectOutline = this.outline_ta.value;
   var revID = this.outline_ta.getAttribute('revID');
   this.helper.show_loading(true);
   new Ajax.Request(window.location.href, {
    method:'post',
    parameters:{s:p, requestType:'save_outline', projectOutline:projectOutline,revID:revID},
    onSuccess: function(transport) {
     var response = transport.responseText.evalJSON();
     this.helper.show_loading(false);
     if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
     this.helper.notify("Saved");
     this.swap_revisions(response.revisions);
     this.outline_ta.setAttribute('revID', response.revID);
    }.bind(this)
   });
  },
  get:function(revID) {
   this.stopEditing(false);
   this.helper.show_loading(true);
   new Ajax.Request(window.location.href, {
    method:'post',
    parameters:{s:p, requestType:'get_outline', revID:revID},
    onSuccess: function(transport) {
     var response = transport.responseText.evalJSON();
     this.helper.show_loading(false);
     if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
     this.swap_outline(response);
    }.bind(this)
   });
  },
  swap_outline:function(outline) {
   var p =  $('outline').down('div.body').down('p')
   if (outline.viewing_diffs==1) p.className='rev';
   p.setStyle("height", "100%");
   p.update(outline.outline);
   p.setAttribute('revID', outline.revID),
   p.setAttribute('locked',outline.locked);
  },
  swap_revisions:function(r){
   if (!r || !$('revisions')) return;
   $('revisions').update(r);
  },
  adjustTextAreaHeight: function(ta) {
    if (ta.scrollHeight > ta.clientHeight && !window.opera) ta.style.height = (ta.scrollHeight)+14 + 'px';
  }
})

var Scenes = Class.create({
  initialize:function(editable) {
   if (editable==1) this.initSortable();
   this.registerEvents();
   this.helper = new ScreenplayHelper();
  },
  registerEvents: function() {
    if ($('scenes')) Event.observe('scenes','click',this.clickListener.bind(this));
    if ($('deleted_scenes')) Event.observe('deleted_scenes','click',this.clickListener.bind(this));
  },
  clickListener:function(event) {
   var link = Event.findElement(event,'a');
   if(!link) return;
   switch (link.className.split(' ')[0]) {
    case 'view_details':
     this.scene_details(link,true);
     break;
   }
  },
  initSortable: function() {
    if (!$('scenes')) { return; }
    Sortable.create('scenes',{
      tag:'div',
      handle:'handle',
      scroll: window,
      onUpdate:function(el){ this.save_sequence(Sortable.sequence('scenes'));  }.bind(this)
    })
  },
  scene_details:function(scene) {
   var scene_id = (scene) ? scene.getAttribute('scene') : 0;
   var editable = (scene) ? scene.getAttribute('edit') : 0;
   this.lightbox=new Panel({
     url:this.paths['scene_details'] + "?s=" + scene_id,
     panelId:'viewing_scene',
     panelClass:'workspace scene_details',
     displayOverlay:true,
     loadingText:'&nbsp;',
     enableClickOut:false,
     onLoadComplete:function(){ this.create_editor(scene_id, editable); }.bind(this),
     onClose:function(){ this.destroy_editor(); }.bind(this)
   }).open();
   //this.lightbox.open();
  },
  branch_scene:function(scene_id) {
   this.lightbox=new Panel({
     url:this.paths['scene_branch'] + "?s=" + scene_id,
     panelId:'viewing_scene',
     panelClass:'workspace',
     displayOverlay:true,
     loadingText:'&nbsp;',
     enableClickOut:false,
     onLoadComplete:function(){ this.create_editor(scene_id); }.bind(this),
     onClose:function(){ this.destroy_editor(); }.bind(this)
   }).open();
  },
  save_sequence:function(sequence) {
   this.helper.show_loading(true);
   new Ajax.Request(window.location.href, {
    method:'post',
    parameters:{s:p, requestType:'reorderScenes', sequence:sequence.toJSON()},
    onSuccess: function(transport) {
     var response = transport.responseText.evalJSON();
     this.helper.show_loading(false);
     if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
     if (response.msg) { this.helper.notify(response.msg); }
     this.complete_sequence(sequence);
    }.bind(this)
   });
  },
  complete_sequence:function(sequence) { //Update scene numbers on each scene.
    this.helper.show_loading(false);
    sequence.each(function(scene_id, i) { $('el_' + scene_id).down('span.scene_number').update((i+1) + "."); });

  },
  create_editor:function(scene_id, editable) {
    this.editor = new SceneEditor(scene_id, this.lightbox, editable);

    if ($('viewing_scene')) {
      //pb_debug('trying to set height of lightbox')
      //$('viewing_scene').setStyle({height:'800px'});
      //this.lightbox.setPosition();
    }
  },
  destroy_editor:function() {
    var reload = this.editor.dirty;
    this.editor = null;
    if (reload) this.helper.refresh_page();
  },
  add_scene:function() {
    this.scene_details();
  },
  toggle_deleted:function() {
    Effect.toggle($('deleted_scenes'), 'Blind', { duration: 1.0});
  },
  set_paths:function(p) {
   this.paths = p;
  }
})

var SceneEditor = Class.create({
  initialize:function(scene_id, panel, launch_editable) {
    this.editing=false;
    this.registerEvents();
    this.helper = new ScreenplayHelper();
    this.scene_id=scene_id;
    this.dirty=false;
    if (panel) this.panel = panel;
    if (scene_id=='0' || launch_editable) { this.edit(); }
  },

  registerEvents: function() {

    Event.observe(document,'keydown',this.keyDownListener.bind(this));
    if ($('existing_branches')) Event.observe('existing_branches','mousedown',this.mouseListener.bind(this));
    if ($('existing_branches')) Event.observe('existing_branches','mouseup',function(event){Event.stop(event)});
    if ($('scene_save_button')) Event.observe('scene_save_button','click',this.saveButtonListener.bind(this));
    if ($('scene_quick_save_button')) Event.observe('scene_quick_save_button','click',this.quickSaveButtonListener.bind(this));
    if ($('scene_edit_button')) Event.observe('scene_edit_button','click',this.editButtonListener.bind(this));
    if ($('scene_lock_button')) Event.observe('scene_lock_button','click',this.lockButtonListener.bind(this));
    if ($('scene_unlock_button')) Event.observe('scene_unlock_button','click',this.unlockButtonListener.bind(this));
    if ($('scene_delete_button')) Event.observe('scene_delete_button','click',this.deleteButtonListener.bind(this));
    if ($('scene_restore_button')) Event.observe('scene_restore_button','click',this.restoreButtonListener.bind(this));
    if ($('create_branch_button')) Event.observe('create_branch_button','click',this.createBranchButtonListener.bind(this));
  },
  mouseListener:function(event) {

    if(Event.findElement(event,'textarea')) return;
    if (e = Event.findElement(event, 'input')) {
      if (wrapper = e.up('div.existing_branches')) this.inputListener(e);
      return;
    }

    //Event.stop(event);
  },
  keyDownListener:function(event) {
    var textarea = Event.findElement(event,'textarea');
    if(!textarea) return;
    this.adjustTextAreaHeight(textarea);
  },
  setButtons:function() {
   $('scene_save_button').disabled=!(this.editing);
   $('scene_edit_button').disabled=(this.editing);
  },
  saveButtonListener:function() { this.save(true); },
  quickSaveButtonListener:function() { this.save(false); },
  editButtonListener:function() { this.edit(); },
  lockButtonListener:function() { this.lock(true); },
  unlockButtonListener:function() { this.lock(false); },
  deleteButtonListener:function() { this.delete_scene(); },
  restoreButtonListener:function() { this.restore_scene(); },
  createBranchButtonListener:function() { this.create_branch(); },
  inputListener:function(i) {
    this.set_primary_branch($(i).value);
  },
  edit:function(container) {
   var scene = $('edit_scene');
   if (!scene || scene.getAttribute('locked')==1) return;
   this.editing=true;
   this.setButtons();
   var fields = scene.select('p');

   var scene_title=fields[0];
   var scene_body=fields[1];
   this.title_ta = new Element('textarea');
   this.body_ta = new Element('textarea');
   if (scene.getAttribute('revID') !=0) {
    this.title_ta.value=this.helper.clean_string(scene_title.innerHTML).gsub('<br>', '\n');
    this.body_ta.value=this.helper.clean_string(scene_body.innerHTML).gsub('<br>', '\n');
   }
   this.title_ta.className='scene_title';
   this.title_ta.setStyle({width:'535px',height:scene_title.getHeight()+'px'});
   this.body_ta.setStyle({width:'535px',height:scene_body.getHeight()+'px'});

   if(this.title_ta.getHeight() < 20) this.title_ta.setStyle({height:'20px'});
   if(this.body_ta.getHeight() < 100) this.body_ta.setStyle({height:'100px'});

   scene.insert(this.title_ta);
   scene.insert(this.body_ta);
   this.adjustTextAreaHeight(this.body_ta);
   scene_title.remove();
   scene_body.remove();

   $('save_controls').show();
   this.title_ta.focus();
  },
  stopEditing:function(restore) {
   if (!this.title_ta) return;
   var p_title = new Element('p').update("&nbsp;");
   p_title.setStyle("height", this.title_ta.getHeight());

   var p_body = new Element('p').update("&nbsp;");
   p_body.setStyle("height", this.title_ta.getHeight());

   this.title_ta.insert({after:p_title});
   this.title_ta.remove();
   this.title_ta=null;

   this.body_ta.insert({after:p_body});
   this.body_ta.remove();
   this.body_ta=null;

   this.editing=false;
   this.setButtons();
   if (restore) this.get();
    $('save_controls').hide();
  },
  save:function(do_exit) {
   if (!this.title_ta || !this.body_ta) { return; }
   this.dirty=true;
   var is_new = ($('edit_scene').getAttribute('new')==1) ? true : false;
   var send_scene_id = (is_new) ? "newScene" : this.scene_id;
   var edit_type = (is_new) ? "add" : "edit";
   this.exit_after_save=do_exit
   this.helper.show_loading(true);
   new Ajax.Request(window.location.href, {
    method:'post',
    parameters:{s:p, requestType:'saveScene', sceneID:send_scene_id,sceneTitle:this.title_ta.value, sceneDescription:this.body_ta.value, editType:edit_type},
    onSuccess: function(transport) {
     var response = transport.responseText.evalJSON();
     this.helper.show_loading(false);
     if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
     this.helper.lightbox_notify(response.msg)
     if ((!this.scene_id || this.scene_id==0) && response.sceneID)  {
      this.scene_id = response.sceneID;
      $('edit_scene').setAttribute('new',0);
     }

     if (this.exit_after_save && this.panel) this.panel.close();

    }.bind(this)
   });
  },
  lock:function(s) {
    this.dirty=true;
    var l = (s) ? 1 : 0;
    this.helper.show_loading(true);
    new Ajax.Request(window.location.href, {
      method:'post',
      parameters:{s:p, requestType:'lockScene', sceneID:this.scene_id,lock:l},
      onSuccess: function(transport) {
       var response = transport.responseText.evalJSON();
       this.helper.show_loading(false);
       if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
       this.lock_result(response);
      }.bind(this)
    });
  },
  lock_result:function(response) {
    $('scene_unlock_button').toggle();
    $('scene_lock_button').toggle();
  },
  delete_scene:function(s) {
    this.dirty=true;
    this.helper.show_loading(true);
    new Ajax.Request(window.location.href, {
      method:'post',
      parameters:{s:p, requestType:'deleteScene', sceneID:this.scene_id},
      onSuccess: function(transport) {
       var response = transport.responseText.evalJSON();
       this.helper.show_loading(false);
       if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
       if (this.panel)  this.panel.close();
      }.bind(this)
    });
  },
  restore_scene:function(s) {
    this.dirty=true;
    this.helper.show_loading(true);
    new Ajax.Request(window.location.href, {
      method:'post',
      parameters:{s:p, requestType:'restoreScene', sceneID:this.scene_id},
      onSuccess: function(transport) {
       var response = transport.responseText.evalJSON();
       this.helper.show_loading(false);
       if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
       if (this.panel)  this.panel.close();
      }.bind(this)
    });
  },
  create_branch:function() {
    this.dirty=true;
    this.helper.show_loading(true);
    var branchType =  $$('input:checked[type="radio"][name="branch_type"]').pluck('value');
    var branchDescription = $('branch_description').value;
    new Ajax.Request(window.location.href, {
      method:'post',
      parameters:{s:p, requestType:'createBranch', sceneID:this.scene_id, branchType:branchType, branchDescription:branchDescription},
      onSuccess: function(transport) {
       var response = transport.responseText.evalJSON();
       this.helper.show_loading(false);
       if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
       if (this.panel)  this.panel.close();
      }.bind(this)
    });
  },
  set_primary_branch:function(branch_id) {
      this.dirty=true;
      this.helper.show_loading(true);
      new Ajax.Request(window.location.href, {
        method:'post',
        parameters:{s:p, requestType:'setPrimaryBranch', sceneID:this.scene_id,branchID:branch_id},
        onSuccess: function(transport) {
         var response = transport.responseText.evalJSON();
         this.helper.show_loading(false);
         if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
         this.helper.lightbox_notify(response.msg)
        }.bind(this)
      });
  },
  adjustTextAreaHeight: function(ta) {
   if (ta.scrollHeight > ta.clientHeight && !window.opera) ta.style.height = (ta.scrollHeight)+14 + 'px';
  }
})

var Toolbar = Class.create({
  initialize:function() {
    this.registerEvents();
    this.helper = new ScreenplayHelper;
    Event.observe('toolbar','click',this.clickListener.bind(this));
  },
 registerEvents: function() {
    if ($('project_dropdown_link')) Event.observe('project_dropdown_link','click',this.toggleProjectDropdown.bind(this));
  },
  clickListener: function(event) {
   var link = Event.findElement(event,'a');
   if(!link) return;
   switch (link.className) {
     case 'entry_privacy':
       this.togglePrivacy(link);
     break;
   }
  },
 set_project_link:function(title,url) {
   $('project_link').update(unescape(title));
   $('project_link').setAttribute('href', url);
 },
 set_project_dropdown:function(paths) {
     var d = new Element('ul');
     paths.collect(function(p) { d.insert(new Element('li').update(new Element('a', {href:p.url}).update(p.title))) }.bind(this));

     this.dropdown=new Panel({
        content:d,
        positionRelativeTo:'project_dropdown_link',
        position:'fixed',
        hooks:["BR","TR"],
        offsetY:0,
        offsetX:0,
        panelClass:'project_dropdown',
        displayOverlay:false,
        excludeFromClickOut:['project_dropdown_link'],
        enableClickOut:true
      })
  },
  toggleProjectDropdown:function() {
   if(this.dropdown.element.visible()) {
    this.dropdown.close();
   } else {
    this.dropdown.open();
   }
  },
 togglePrivacy:function(link) {
    this.helper.show_loading(true);
    new Ajax.Request(window.location.href, {
      method:'post',
      parameters:{s:p, requestType:'set_privacy'},
      onSuccess: function(transport) {
       var response = transport.responseText.evalJSON();
       this.helper.show_loading(false);
       if (!response || response.error==1) { this.helper.throw_error({msg:response.msg}); return; }
       this.helper.notify("Privacy set");
       link.up('div.switch_container').replace(response.html)
      }.bind(this)
    });
  }

})


var map_lookup=[];

function screenplay_proxy() { this.helper = new ScreenplayHelper();  }
screenplay_proxy.prototype=new penumbra();
saver=new screenplay_proxy();

screenplay_proxy.prototype.save_element=function(container) {
 if (!container) { pb_debug('no container passed to save_element'); return; }
 content = container.select('textarea').collect(function(ta){return $F(ta)});

 o={requestType:'submitElement', iscreenplay:1}
 o.sceneID=container.getAttribute("scene");
 o.mapID= (map_lookup[o.sceneID]) ?  map_lookup[o.sceneID] : container.getAttribute("map"); //Look to see if we have a map for this scene.

 o.elementID=container.getAttribute("id");
 o.elementType=container.getAttribute("type");
 o.after = container.getAttribute("after");

 if (container.getAttribute('new') == "true") {
  o.newElement=1;
  var append = (container.getAttribute("append")==1) ? 1 : 0;
  o.insertType=(append==1) ? 0 : 1;
  o.trackID="screenplay/new_element";
  container.setAttribute("new","false");
 } else {
  o.newElement=0;
  o.trackID="screenplay/edit_element";
 }

 switch(o.elementType.toString()){
  case '100':
  case '200':
  case '400':
  case '500':
   o.content=content[0];
   break;
  case '300':
   o.character=content[0];
   o.content=content[1];
  if (!isset(o.character) || !isset(o.content)) { alert ("Please enter both a character name and dialogue."); return; }
   break;
 }

 if (!isset(o.character) && !isset(o.content) && o.newElement==1) { return; } //User didn't submit anything.

 if (!o.mapID) {

  var e = {msg:'We lost sync with the server--please refresh your page (no map). Here&rsquo;s the last element you wrote:<br>'};
  if (o.character) e.msg+=o.character+"<br>";
  e.msg+=o.content;
  this.helper.throw_error(e);
  //TODO: Need to log JS error
  return;
 }

 if (o.newElement==1 && !o.after && append !=1) { //New element but no after. Will show up at top of screenplay.
  var e = {msg:'You created a new element but we lost track of which one it should come after. Here&rsquo;s the last element you wrote:<br>'};
  if (o.character) e.msg+=o.character+"<br>";
  e.msg+=o.content;
  this.helper.throw_error(e);
  //TODO: Need to log JS error
  return;
 }

 if (pb_screenplay.sandboxMode==1) { o.sandbox=1; }

 saving = container;
 this.working()
 this.irequest(o,'saver', 'save_element_return')
}

screenplay_proxy.prototype.save_element_return=function(obj){

 var response = obj.responseText.evalJSON();
 if (!response || response.error==1){ this.helper.throw_error({msg:response.msg}); return; }
 if (response.msg) { this.helper.notify(response.msg); }
 if (o.character) {
  if(pb_screenplay.characterCompleter.listArray.indexOf(o.character) == -1) {
   pb_screenplay.characterCompleter.listArray.push(o.character);
  }
 }
 this.update_map_for_scene(response.scene, response.map);
 if (saving) {

  saving.setAttribute("id", response.id);
  try {
    var next_container = saving.up('div.element_container').next("div");
    next_container.down('div.body').down('div').setAttribute("after", response.id);
  } catch(e) {
    pb_debug("Could not set id on next container. If you're saving the last element this is correct")
  }
 }

 saving.up('div.element_container').replace(response.html);

 if(response.prompt) {
   $('sandbox_prompt').update(response.prompt);
 }
 this.helper.show_loading(false);

}

screenplay_proxy.prototype.delete_element=function(container) {
 if (!container.getAttribute("id")) { return; }
 o={requestType:'deleteElement', iscreenplay:1, sceneID:container.getAttribute("scene"), elementID:container.getAttribute("id")}
 o.mapID= (map_lookup[o.sceneID]) ?  map_lookup[o.sceneID] : container.getAttribute("map");
 this.working()
 o.trackID="screenplay/delete_element";
 this.irequest(o,'saver', 'delete_element_return')
}

screenplay_proxy.prototype.delete_element_return=function(obj){
 var response = obj.responseText.evalJSON();
 if (!response || response.error==1){ this.helper.throw_error({msg:response.msg}); return; }
 this.update_map_for_scene(response.scene, response.map);
 if (response.msg) { this.helper.notify(response.msg); }
 this.helper.show_loading(false);
}

screenplay_proxy.prototype.working=function() {
 this.helper.show_loading(true);
}

screenplay_proxy.prototype.update_map_for_scene=function(scene, map) {
 map_lookup[scene]=map;
}

screenplay_proxy.prototype.load_revs=function(scene, map, element, container) {
 o={requestType:'showElementRevs', iscreenplay:1, sceneID:scene, mapID:map, elementID:element, active:element}
 this.working();
 rev_container = container;
 o.trackID="screenplay/show_revisions";
 this.irequest(o,'saver', 'rev_return')
}

screenplay_proxy.prototype.rev_return=function(obj) {
 this.helper.show_loading(false);
 var response = obj.responseText.evalJSON();
 if (!response || response.error==1){ this.helper.throw_error({msg:response.msg}); return; }
 pb_screenplay.show_revs(rev_container, response);
}

screenplay_proxy.prototype.revert_element=function(map, scene, element, rev, container) {
 map= (map_lookup[scene]) ?  map_lookup[scene] : map;
 o={requestType:'revertElement', iscreenplay:1, sceneID:scene, mapID:map, elementID:element, revID:rev}
 this.working();
 revert_container = container;
 o.trackID="screenplay/revert_element";
 this.irequest(o,'saver', 'revert_return')
}

screenplay_proxy.prototype.restore_element=function(map, scene, element, rev, container) {
 map= (map_lookup[scene]) ?  map_lookup[scene] : map;
 o={requestType:'restoreDeleted', iscreenplay:1, sceneID:scene, mapID:map, elementID:element, revID:rev}
 this.working();
 revert_container = container;
 o.trackID="screenplay/restore_element";
 this.irequest(o,'saver', 'revert_return')
}

screenplay_proxy.prototype.revert_return=function(obj) {
 this.helper.show_loading(false);
 var response = obj.responseText.evalJSON();
 if (!response || response.error==1){ this.helper.throw_error({msg:response.msg}); return; }
 this.update_map_for_scene(response.scene, response.map);
 if (response.msg) this.helper.notify(response.msg)
 if (response.restore==1) {
  revert_container.up('div.element_container').replace(response.html);
 } else {
  revert_container.up('div.element_container').up('div.element_container').replace(response.html);
 }
}

screenplay_proxy.prototype.load_comments=function(collection_id, container) {
 o={requestType:'returnComments', iscreenplay:1, collectionID:collection_id}
 o.trackID="screenplay/comments_request";
 this.working();
 comments_container = container;
 this.irequest(o,'saver','comments_return')
}

screenplay_proxy.prototype.comments_return=function(obj) {
 this.helper.show_loading(false);
 pb_screenplay.show_comments(comments_container, obj.responseText);
}
