﻿var UPlatform = null;
var UPLATFORM = {
  BOOKUPDATED: "uplatform:bookupdated",
  DOCUMENTUPDATED: "uplatform:documentupdated",
  SHOWALIENCONTENT: "uplatform:showaliencontent",
  BOOKERROR: "uplatform:bookerror",
  BEFOREOPENDOCUMENT: "uplatform:beforeopendocument",
  HISTORYUPDATED: "uplatform:historyupdated",
  TREESELECTNODE: "uplatform:treeselectnode",
  LISTSELECTNODE: "uplatform:listselectnode", 
  SHOWLINKMANAGEMENT: "uplatform:showlinkmanagement",
  HIDELINKMANAGEMENT: "uplatform:hidelinkmanagement",
  FAVORITEDOCUMENTUPDATED: "uplatform:favoritedocumentupdated",
  FAVORITESUPDATED: "uplatform:favoritesupdated",
  DOCUMENTTOCCHANGED: "uplatform:documenttocchanged",
  QUERY: {
    BEFOREEXECUTE: "uplatform:querybeforeexecute"
  },
  BOOKCOMPILER: {
    UPDATED: "uplatform:bookcompilerupdated",
    USEUPDATE: "uplatform:bookcompileruseupdate"    
  },
  RELEASE: {
    VALUESUPDATED: "uplatform:releasevaluesupdated",
    CHANGEFAILED: "uplatform:releasechangefailed",
    CHANGED: "uplatform:releasechanged",
    LIBRARYCHANGEFAILED: "uplatform:releaselibrarychangefailed",    
    LIBRARYCHANGED: "uplatform:releaselibrarychanged"    
  },
  VAULTSTORAGE: {
    DATAUPDATED: "uplatform:vaultstoragedataupdated",
    DATASAVEREQUEST: "uplatform:vaultsaverequest",
    OPENFILENAMEREQUEST: "uplatform:vaultopenfilenamerequest",
    MANAGEMENTREQUEST: "uplatform:vaultmanagementrequest",
    COMMANDEXECUTED: "uplatform:vaultcommandexecuted"
  }  
}

Event.observe(document, "application:preloadauthorized", OnUPlatformApplicationLoadAuthorized);

function OnUPlatformApplicationLoadAuthorized()
{
  if ((UPlatform == null) && (Proxy.IsContext(self))) {  
    UPlatform = new KMUPlatform();          
  }
}

function KMUPlatform()
{
  var _contentFrame = "contentframe"; // Default frame name, update in OnApplicationPreLoaded event
  var _contentFrameHooked = false;
  var _documentTree = null;
  var _libraryTree = null;
  var _delayedOpenDocumentRequest = null;  
  
  this.SetContentFrame = _SetContentFrame;
  this.SetDocumentTree = _SetDocumentTree;
  this.SetLibraryTree = _SetLibraryTree;
  this.GetContentFrame = _GetContentFrame;
  this.GetDocumentTree = _GetDocumentTree;
  this.GetLibraryTree = _GetLibraryTree;  
  this.GetDocumentDeepLink = _GetDocumentDeepLink;  
  this.UpdateContent = _UpdateContent;  
  this.CurrentBook = _CurrentBook;
  this.CurrentDocument = _CurrentDocument;
  this.OpenDocument = _OpenDocument;  
  this.OpenDocumentEx = _OpenDocumentEx;
  this.ScrollInContentFrame = _ScrollInContentFrame;
  this.OpenSlotLicenseDocument = _OpenSlotLicenseDocument;
  this.ExecuteOpenDocumentRequest = _ExecuteOpenDocumentRequest;
  this.ExecuteDelayedOpenDocumentRequest = _ExecuteDelayedOpenDocumentRequest;
  this.OpenExternal = _OpenExternal;
  this.History = new KMUPlatformHistory();
  this.Quest = new KMUPlatformQuest();  
  this.SearchService = new KMUPlatformSearchService();
  this.LinkManagement = new KMUPlatformLinkManagement();  
  this.Favorites = new KMUPlatformFavorites();
  this.Release = new KMUPlatformRelease();   
  this.BookCompiler = new KMUPlatformBookCompiler();
  this.FeedBack = new KMUPlatformFeedBack();
  this.VaultStorage = new KMUPlatformVaultStorage();
     
  _Create();
     
  function _Create()
  {
    Event.observe(Proxy.GetEventSink(), "magma:scrolldocument", _OnScrollDocument);
    Event.observe(Proxy.GetEventSink(), "magma:newbook", _OnNewBook);
    Event.observe(Proxy.GetEventSink(), "magma:newdocument", _OnNewDocument);
    Event.observe(Proxy.GetEventSink(), "magma:newbookerror", _OnNewBookError);    
    Event.observe(Proxy.GetEventSink(), "magma:documenttoc", _OnDocumentTocContents);
    Event.observe(Proxy.GetEventSink(), "magma:documenttocdeltacontent", _OnDocumentTocContents);
    Event.observe(Proxy.GetEventSink(), UPLATFORM.RELEASE.LIBRARYCHANGED, _OnDocumentNeedsUpdate);     
    Event.observe(Proxy.GetEventSink(), UPLATFORM.RELEASE.LIBRARYCHANGED, _OnNoBook);
    Event.observe(Proxy.GetEventSink(), UPLATFORM.RELEASE.CHANGED, _OnNoBook);
    Event.observe(Proxy.GetEventSink(), MAGMA.EVENT.APPLICATION.START, _OnNoBook);    
  }
  
  function _GetDocumentDeepLink()
  {
    var url;
    if (Proxy.GetValues().Application.IsServer) {   
      url = Proxy.GetValues().Application.RootUrl;
    } else if (typeof Proxy.GetValues().Application.InternetUrl == "string") {      
      url = Proxy.GetValues().Application.InternetUrl;      
    } else {
      url = Proxy.GetValues().Application.RootUrl;
    }
    var currentdocument = _CurrentDocument();
    
    if (currentdocument) {
      if (url.lastIndexOf("/") != url.length) {
        url += "/";
      }
      url += "?action=login&externalaction=linkmanager&id=" + currentdocument.Id;      
    }      
    return escape(url);
  }
   
  function _OnNewBookError(event)
  {        
    Proxy.GetEventSink().fire(UPLATFORM.BOOKERROR, event.memo.Parameters);
  }
  
  function _OnDocumentTocContents(event)
  {
    var hasdata = (((!Object.isUndefined(event.memo.HasData)) && (event.memo.HasData)) || 
                   ((!Object.isUndefined(event.memo.Parameters.message)) && (event.memo.Parameters.message != "")));
    Proxy.GetEventSink().fire(UPLATFORM.DOCUMENTTOCCHANGED, {HasData: hasdata});        
  }
  
  function _OnNewBook(event)
  {
    _DoNewBook(event.memo.Parameters.json);             
  }
  
  function _OnNoBook()
  {
    _DoNewBook(null);
    Proxy.GetEventSink().fire(UPLATFORM.DOCUMENTUPDATED, null);  
  }
  
  function _DoNewBook(book)
  {  
    var frame = Proxy.GetContext();
    if (frame) {
      if (book) {
        var currentdocument = _CurrentDocument();
        frame.CurrentBook = book;
        frame.CurrentBook.Document = currentdocument;         
      } else {
        frame.CurrentBook = null;        
      }
      Proxy.GetEventSink().fire(UPLATFORM.BOOKUPDATED, frame.CurrentBook);           
    }
  }
  
  function _OnDocumentNeedsUpdate(event)
  {      
    if (!event.memo.InDirect) {
      _UpdateContent();   
    }      
  }
  
  function _OnNewDocument(event)
  {      
    var book = _CurrentBook();
    if (book != null) {
      if (typeof event == "object") {
        book.Document = event.memo.Parameters.json;            
      }
      // Seen that although book.Document could be null, it appears to hold a strange object in observer.
      Proxy.GetEventSink().fire(UPLATFORM.DOCUMENTUPDATED, book.Document);  

      // Call optional method in content frame indicating it's contents was fully loaded
      // and document information is available
      if ((_contentFrame) && (_contentFrame.DocumentLoaded)) {
        try {
          _contentFrame.DocumentLoaded();
        } catch(e) {
        }
      }
    }        
  }
    
  function _OnScrollDocument(event)
  {     
    // UPlatform scroll request
    if ((event.memo.Parameters.documentanchor) && (_InitializeContentFrame())) {
      if (event.memo.Parameters.documentanchor === "") {        
        _contentFrame.window.scrollTo(0, 0);
      } else {
        _ScrollInContentFrame(unescape(event.memo.Parameters.documentanchor));
      }   
    }
     
    // Update document title and call new document in case it's a new location within the same document 
    if (event.memo.Parameters.jsonsamedocument) {
      var doc = _CurrentDocument();
      if (doc) {       
        doc.Title = event.memo.Parameters.documenttitle;
        _OnNewDocument();
      }      
    }    
  }
  
  function _ScrollInContentFrame(anchor)
  {
    if ((typeof anchor == "string") && (anchor != "") && (_contentFrame)) {
      var anchorelement = _contentFrame.document.getElementById("display_" + anchor); // attempt to locate display anchor first
      if (anchorelement == null) {
        anchorelement = _contentFrame.document.getElementById(anchor);
      }
      
      if (anchorelement) {                    
        // -18 is correction to make sure title is in view
        _contentFrame.window.scrollTo(0, Element.cumulativeOffset(anchorelement).top-18);
      }            
    }
  }
  
  function _OnLoadDocument(event)
  {      
    // Called when iframe reports document as loaded
    if ((_documentTree) && (_documentTree.GetDeltaFrame) && (_documentTree.GetDeltaFrame().setData)) {              
      _documentTree.GetDeltaFrame().setData("documentloaded");      
    }
    
    if ((_libraryTree) && (_libraryTree.GetDeltaFrame) && (_libraryTree.GetDeltaFrame().setData)) {              
      _libraryTree.GetDeltaFrame().setData("documentloaded");      
    }      
    
    if ((Proxy.Frames.Delta()) && (Proxy.Frames.Delta().setData)) {
      Proxy.Frames.Delta().setData("documentloaded");    
    }
  }
    
  function _InitializeContentFrame()
  {
    if (_contentFrame != null) { 
      if (typeof _contentFrame == "string") {
        _contentFrame = Proxy.Frames.ByName(_contentFrame);
      } 
      
      if (_contentFrame != null) {
        if (!_contentFrameHooked) {          
          var frame = Proxy.Frames.ObjectById(_contentFrame.window.name);
          if (frame) {          
            Event.observe(frame, "load", _OnLoadDocument);
            _contentFrameHooked = true;
          }
        }
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }    
  }
  
  function _SetContentFrame(value)
  {
    _contentFrame = value;
  }
  
  function _SetDocumentTree(value)
  {
    _documentTree = value;
  }
  
  function _SetLibraryTree(value)
  {
    _libraryTree = value;
  }
  
  function _GetContentFrame(value)
  {
    return _contentFrame;
  }
  
  function _GetDocumentTree(value)
  {
    return _documentTree;
  }
  
  function _GetLibraryTree(value)
  {
    return _libraryTree;
  }  
  
  function _UpdateContent(custom)
  {        
    if (_InitializeContentFrame()) {   
      var baseurl;
      if (Proxy.GetValues().Application.IsServer) {        
        baseurl = Proxy.GetValues().Application.RootUrl;
      } else {
        baseurl = Proxy.GetValues().Application.Module;
      }
    
      if ((typeof custom == "string") && (custom !== "")) {                  
        if (custom.startsWith(baseurl)) {           
          _contentFrame.location.replace(custom);  
        } else {
          // alien location          
          _contentFrame.document.open();
          _contentFrame.document.write("<html>" +
            "<head><style>body { overflow:hidden;width:100%;height:100%;margin:0px; }</style></head>" +
            "<body scroll='no'><iframe src='" + custom + "' style='width:100%;height:100%;' frameborder='0'></iframe></body>" +
            "</html>");
          _contentFrame.document.close();
          
          Proxy.GetEventSink().fire(UPLATFORM.SHOWALIENCONTENT);
        }
      } else {
        var url = baseurl;
            
        if ((custom) && (custom.toQueryString)) {
          url += "?sid=" + Proxy.GetValues().User.Sid + "&" + custom.toQueryString();                  
          _contentFrame.location.replace(url);
        } else {        
          var defaultrequest = /upaction=document/;
          if (defaultrequest.test(_contentFrame.location.href)) {
            _contentFrame.location.reload(true)
          } else {
            url += "?upaction=document&_sro=true&sid=" + Proxy.GetValues().User.Sid;                    
            _contentFrame.location.replace(url);
          }           
        }
      }     
    }		  
  }
  
  function _CurrentBook()
  {
    var frame = Proxy.GetContext();
    if ((frame) && (frame.CurrentBook)) {
      return frame.CurrentBook;
    } else {
      return null;
    }   
  }
  
  function _CurrentDocument()
  {
    var book = _CurrentBook();
    if (book != null) {
      return book.Document;
    } else {
      return null;
    }
  }
    
  function _OpenSlotLicenseDocument(id, options)
  {
    // Adds document to slot license list and opens document.
    _OpenDocumentExInternal(id, "slotlicenseitemadd", options);
  }
    
  function _OpenDocument(id, origin, fromHistory)
  {
    var options = null;
    
    if ((typeof origin == "string") ||
        (typeof fromHistory == "boolean")) {
      options = new Hash();
      if (typeof origin == "string") {
        options.set("origin", origin);
      }      
      
      if (typeof fromHistory == "boolean") {
        options.set("historynavigation", false);
      }
    }
      
    _OpenDocumentEx(id, options);     
  } 
  
  function _OpenDocumentEx(id, options)
  {
    _OpenDocumentExInternal(id, null, options);
  }
  
  function _OpenDocumentExInternal(id, actionId, options)
  {
    if ((id != null) && (typeof id == "string") && (id != "")) {
      if ((options == null) || (Object.isUndefined(options)) ||
          (!options.toQueryString)) {
        options = new Hash();
      }
      
      if (typeof options.get("origin") != "string") {
        options.set("origin", "document");
      }
      
      if (typeof options.get("historynavigation") != "boolean") {
        options.set("historynavigation", false);
      }
      
      if ((typeof actionId != "string") || (actionId == "")) {
        actionId = "opendoc";
      }
            
      var request = new Hash({"upaction": actionId, "id": id}).toQueryString() +
        "&" + options.toQueryString();
        
      _ExecuteOpenDocumentRequest(request);
    }
  }  
  
  // Centralized method for executing all requests that might close currently
  // loaded document. Functions as a stub for Proxy.Delta.Execute and allows
  // interception, aborting and delaying of actual request.
  function _ExecuteOpenDocumentRequest(request, frame, readOnly)
  {       
    if (request != null) {
      _delayedOpenDocumentRequest = { Result: "allowed", 
        Request: request, Frame: frame, ReadOnly: readOnly };
      
      Proxy.GetEventSink().fire(UPLATFORM.BEFOREOPENDOCUMENT, _delayedOpenDocumentRequest);
      
      if (_delayedOpenDocumentRequest.Result == "allowed") {
        _ExecuteDelayedOpenDocumentRequest();
      } else if (_delayedOpenDocumentRequest.Result == "delayed") {        
        //alert("request delayed");
      } else {        
        _delayedOpenDocumentRequest = null;
        //alert("request aborted");
      }      
    } else {
      _delayedOpenDocumentRequest = null;
    }
  }
  
  function _ExecuteDelayedOpenDocumentRequest()
  {
    if (_delayedOpenDocumentRequest) {            
      Proxy.Delta.Execute(
        _delayedOpenDocumentRequest.Request,
        _delayedOpenDocumentRequest.Frame,
        _delayedOpenDocumentRequest.ReadOnly);
      
      _delayedOpenDocumentRequest = null;
      return true;
    } else {
      return false;
    }
  }
  
  function _OpenExternal(url, windowName)
  {
    if ((url != null) && (typeof url == "string") && (url != "")) {    
      if ((url.indexOf("http://") == -1) && 
          (url.indexOf("https://") == -1) &&
          (url.indexOf("ftp://") == -1)) {        
        url = "http://" + url;
      }
      
      if ((windowName) && (typeof windowName == "string")) {
        window.open(url, windowName);
      } else {
        window.open(url);	
      }
    }    
  } 
}

function KMUPlatformVaultStorage()
{
  var _vaultData = _DefaultVaultData(); 
  var _delayedVaultData = false;
  this.GetVaultData = _GetVaultData;
  this.DataDirty = _DataDirty;
  this.New = _New;
  this.NewDirect = _NewDirect;
  this.Open = _Open;
  this.OpenDirect = _OpenDirect;
  this.Save = _Save;
  this.Management = _Management;
  this.KeyRequest = _KeyRequest;
    
  _Create();
  
  function _Create()
  {
    Event.observe(Proxy.GetEventSink(), UPLATFORM.BEFOREOPENDOCUMENT, _OnBeforeOpenDocument);      
    Event.observe(Proxy.GetEventSink(), "magma:vaultdataupdated", _OnVaultDataUpdated);    
    Event.observe(Proxy.GetEventSink(), MAGMA.EVENT.APPLICATION.START, function() {
      _OnVaultDataUpdated(Proxy.GetStartupInfo()); } );      
  }
  
  function _RestoreXFormData()
  {
    if ((_vaultData != null) && (_vaultData.Data != null)) {
      var formsupport = _GetDocumentFormSupport();
      if (formsupport) {       
        try {
          formsupport.Restore(_vaultData.Data);        
        } catch(ex) {
          alert("Exception while restoring form values. " + ex.message);
        }
      } 
    }    
  }
      
  function _OnVaultDataUpdated(event)
  {      
    if ((event) && (event.memo) && (event.memo.Parameters) && (event.memo.Parameters.VaultData)) {    
      _vaultData = event.memo.Parameters.VaultData;
    } else if ((event) && (event.VaultData)) {    
      _vaultData = event.VaultData;
    } else {
      var frame = Proxy.GetContext();
      if ((frame) && (frame.VaultData)) {
        _vaultData = frame.VaultData;
      } else {      
        _vaultData = _DefaultVaultData();
      }
    }
        
    _FireVaultDataUpdate();
    if (_delayedVaultData) {
      _delayedVaultData = false;
      _RestoreXFormData();
    }    
  }
  
  function _Management()
  {
    if (_vaultData.Enabled) {
      _FireManagementRequest();
    }
  }
  
  function _New()
  {
    if ((_vaultData.Enabled) && (_vaultData.DataAware)) {
      if (_vaultData.Dirty) {
        _FireVaultDataSaveRequest({OriginAction: "new", CallBack: function()
          {
            Proxy.GetContext().UPlatform.VaultStorage.NewDirect();
          }});        
      } else {
        _NewDirect();
      }
    }
  }
  
  function _NewDirect()
  {
    if ((_vaultData.Enabled) && (_vaultData.DataAware)) {
      /*var formsupport = _GetDocumentFormSupport();
      if (formsupport) {                        
        formsupport.Reset();        
      }*/
    
      var list = new Hash({ "sid": Proxy.GetValues().User.Sid, 
        "kmmagmaplatformrequesttype": "newvaultdata", "ajax": "True"});	
   
      try { 
        new Ajax.Request(Proxy.GetValues().Application.Module,
        { method: 'post',
          evalJSON: true,
          parameters: list.toQueryString(),
          onSuccess: function(result) {          
            _vaultData = result.responseJSON.Parameters.VaultData;
            _FireVaultDataUpdate();
            Proxy.GetContext().UPlatform.UpdateContent();
          }
        });		  
      } catch(ex) {      
      } 
    }
  }
  
  function _Open(fileId)
  {
    // Allow save before opening. fileId is optional.
    if (_vaultData.Enabled) {
      if ((_vaultData.DataAware) && (_vaultData.Dirty)) {
        _FireVaultDataSaveRequest({OriginAction: "open", CallBack: function()
          {
            Proxy.GetContext().UPlatform.VaultStorage.OpenDirect(fileId);
          }});        
      } else {
        _OpenDirect(fileId);
      }
    }  
  }
  
  function _OpenDirect(fileId)
  {
    if (_vaultData.Enabled) {
      if ((typeof fileId != "string") || (fileId == "")) {
        // Fire event to obtain filename first
        _FireOpenFileNameRequest({OriginAction: "open", CallBack: function(fileId)
          {
            Proxy.GetContext().UPlatform.VaultStorage.OpenDirect(fileId);
          }});
      } else {
        var list = new Hash({ "sid": Proxy.GetValues().User.Sid, 
          "kmmagmaplatformrequesttype": "openvaultdata", 
          "ajax": "True", "fileid": fileId});	
        try { 
          new Ajax.Request(Proxy.GetValues().Application.Module,
          { method: 'post',
            evalJSON: true,
            parameters: list.toQueryString(),
            onSuccess: function(result) { 
              if ((result.responseJSON.Parameters.VaultData.Document) &&
                  (typeof result.responseJSON.Parameters.VaultData.Document.Redirect == "string")) {
                // We should redirect to requested document first
                _delayedVaultData = true;
                Proxy.GetContext().UPlatform.OpenDocument( 
                  unescape(result.responseJSON.Parameters.VaultData.Document.Redirect), "system", false);
              } else {           
                _delayedVaultData = false;              
                try {            
                  _vaultData = result.responseJSON.Parameters.VaultData;
                } catch(ex) {
                  alert("Exception while handling JSON form data. " + ex.message);
                }
                _FireVaultDataUpdate();
                _RestoreXFormData();
              }
            }
          });		  
        } catch(ex) {      
        }       
      }
    }    
  }
	
	function _GetDocumentFormSupport()
	{
    if ((Proxy) && (Proxy.GetContext()) && (Proxy.GetContext().UPlatform)) {
      var frame = Proxy.GetContext().UPlatform.GetContentFrame();
      if ((frame) && (frame.FormSupport)) {      
        return frame.FormSupport;      
      } else {      
		    return null;
		  }
    } else {    
      return null;
    }
	}
  
  function _Save(folderId, fileName, afterSave)
  {
    if ((_vaultData.Enabled) && (_vaultData.DataAware) &&
        (typeof folderId == "string") && (typeof fileName == "string")) {              
      var list = new Hash({ "sid": Proxy.GetValues().User.Sid, 
        "kmmagmaplatformrequesttype": "savevaultdata", "ajax": "True",
        "folderid": folderId, "filename": fileName});	
        
      var formsupport = _GetDocumentFormSupport();
      if (formsupport) {                        
        formsupport.Store(list);                
      }
			
      try { 
        new Ajax.Request(Proxy.GetValues().Application.Module,
        { method: 'post',
          evalJSON: true,
          parameters: list.toQueryString(),
          onSuccess: function(result) {                      
            _vaultData = result.responseJSON.Parameters.VaultData;
            _FireVaultDataUpdate();
            if (Object.isFunction(afterSave)) {              
              afterSave();
            }
          }
        });		  
      } catch(ex) {      
      } 
    }
  }
    
  function _DefaultVaultData()
  {
    return { Dirty: false, DataAware: false, DataSetId: "", 
      Enabled: false, FolderId: null, FileName: null, DisplayFileName: null,
      ErrorText: null, UnknownFileName: "[unknown]" }
  }
  
  function _OnBeforeOpenDocument(event)
  {               
    if ((_vaultData.Enabled) && (_vaultData.DataAware) && (_vaultData.Dirty)) { 
      event.memo.Result = "delayed";
      
      _FireVaultDataSaveRequest({OriginAction: "close", CallBack: function()
        {
          Proxy.GetContext().UPlatform.ExecuteDelayedOpenDocumentRequest();
        }});       
    }
  }
    
  function _GetVaultData()
  {
    return _vaultData;
  }
  
  function _DataDirty()
  {
    if ((_vaultData.Enabled) && (_vaultData.DataAware) && (!_vaultData.Dirty)) {        
      _vaultData.Dirty = true;
      _vaultData.ErrorText = null;      
      _FireVaultDataUpdate();
      
      // Notify server about dirty document data
      var list = new Hash({ "sid": Proxy.GetValues().User.Sid, 
        "kmmagmaplatformrequesttype": "dirtyvaultdata", "ajax": "True"});	   
      try { 
        new Ajax.Request(Proxy.GetValues().Application.Module,
        { method: 'post',
          evalJSON: true,
          parameters: list.toQueryString()
        });		  
      } catch(ex) {      
      } 
    }          
  } 
  
  function _KeyRequest(afterMethod)
  { 
    var list = new Hash({ "sid": Proxy.GetValues().User.Sid, 
      "kmmagmaplatformrequesttype": "vaultkeyrequest"});	   
    try { 
      new Ajax.Request(Proxy.GetValues().Application.Module,
      { method: 'post',
        evalJSON: true,
        parameters: list.toQueryString(),
        onSuccess: function(result) {                            
          if (Object.isFunction(afterMethod)) {
            afterMethod(result.responseJSON);
          }
        }        
      });		  
    } catch(ex) {      
    }   
  }
  
  function _FireVaultDataUpdate()
  {
    Proxy.GetEventSink().fire(UPLATFORM.VAULTSTORAGE.DATAUPDATED, _vaultData);    
  }
  
  function _FireVaultDataSaveRequest(requestData)
  {
    Proxy.GetEventSink().fire(UPLATFORM.VAULTSTORAGE.DATASAVEREQUEST, requestData);    
  }
  
  function _FireOpenFileNameRequest(requestData)
  {
    Proxy.GetEventSink().fire(UPLATFORM.VAULTSTORAGE.OPENFILENAMEREQUEST, requestData);    
  }
  
  function _FireManagementRequest(requestData)
  {
    Proxy.GetEventSink().fire(UPLATFORM.VAULTSTORAGE.MANAGEMENTREQUEST, requestData);    
  }  
}

function KMUPlatformSearchService()
{
  var _query;

  this.Execute = _Execute;  
  this.ExecuteProperty = _ExecuteProperty;
  this.GetQuery = _GetQuery;
    
  function _ExecuteProperty(property, callBack, options)
  {
    if ((Object.isString(property)) && (Object.isFunction(callBack))) {      
      var command = new Hash({ "sid": Proxy.GetValues().User.Sid,       
        "upaction": "searchclientlookup",
        "__property": property,
        "__output": "json"});	
        
      if ((Object.isUndefined(options)) || (options == null)) {
        options = {};
      }    
      
      if (Object.isUndefined(options.StartPage)) {      
        options.StartPage = 1;
      }
      command.set("__startpage", options.StartPage);
      
      if (Object.isString(options.ServiceId)) {
        command.set("__serviceid", options.ServiceId);
      }               
      
      if (Object.isNumber(options.ResultsPerPage)) {
        command.set("__resultsperpage", options.ResultsPerPage);
      }        
      
      try { 
        new Ajax.Request(Proxy.GetValues().Application.Module,
        { method: 'post',
          evalJSON: true,
          parameters: command.toQueryString(),
          onSuccess: callBack
        });		  		        
      } catch(ex) {      
      }           
    }      
  }    
    
  function _Execute(query, options)
  {
    if ((query != null) && (Object.isString(query))) {  
      _query = query;    
      var command = new Hash({"upaction": "searchclient", "query": query});      
      
      if ((Object.isUndefined(options)) || (options == null)) {
        options = {};
      }
      
      if (Object.isUndefined(options.StartPage)) {      
        options.StartPage = 1;
      }
      command.set("__startpage", options.StartPage);
      
      if (Object.isString(options.ServiceId)) {
        command.set("__serviceid", options.ServiceId);
      }
              
      var request = command.toQueryString(); 
      var scopespecified = (query.indexOf("scope:") >= 0);
      if (Object.isArray(options.QueryOptions)) {
        options.QueryOptions.each(function(item) {
          request += "&" + escape(item.Property) + "=" + escape(item.Value);
          
          if (item.Property.toLowerCase() == "scope") {
            scopespecified = true;
          }
        });
      }
      
      if ((!scopespecified) && (Object.isString(options.DefaultScope)) && (!options.DefaultScope.blank())) {      
        request += "&scope=" + options.DefaultScope;
      }
            
      Proxy.GetEventSink().fire(UPLATFORM.QUERY.BEFOREEXECUTE, query);
      Proxy.Delta.Execute(request);      
    }
  }
  
  function _GetQuery()
  {
    if (Object.isString(_query)) {
      return _query;
    } else {
      return "";
    }
  }
}

function KMUPlatformQuest()
{
  var _justAnd = false;
  
  this.Execute = _Execute;  
  this.CurrentBook = false;
  this.CurrentDocument = false;
  this.JustAnd = false;
  this.IncludeScopes = null;
  this.ExcludeScopes = null;  
  
  function _Execute(query)
  {    
    if ((query != null) && (typeof query == "string")) {      
      var command = new Hash({"upaction": "query", "query": query});
      if ((typeof this.CurrentDocument == "boolean") && (this.CurrentDocument)) {
        command.set("filter", "currentdocument");
      } else if ((typeof this.CurrentBook == "boolean") && (this.CurrentBook)) {
        command.set("filter", "currentbook");
      }
      
      if ((typeof this.JustAnd == "boolean") && (this.JustAnd)) {
        command.set("justand", "true");
      }
        
      var iscope = _GetScopesQueryString(this.IncludeScopes, "iscope");
      var escope = _GetScopesQueryString(this.ExcludeScopes, "escope");
      var request = command.toQueryString();
      if (iscope != "") {
        request += "&" + iscope;
      }      
      if (escope != "") {
        request += "&" + escope;
      }            
            
      Proxy.GetEventSink().fire(UPLATFORM.QUERY.BEFOREEXECUTE, query);
      Proxy.Delta.Execute(request);
    }
  }

  function _GetScopesQueryString(scopes, type)
  {
    var result = "";
    if ((Object.isArray(scopes)) && (Object.isString(type))) {      
      scopes.each(function(scope) {
        if (result != "") {
          result += "&";
        }
        result += type + "=" + escape(scope);  
      });      
    } 
    return result;
  }  
}

function KMUPlatformLinkManagement()
{
  this.Open = _Open;

  _Create();
  
  function _Create()
  {
    Event.observe(Proxy.GetEventSink(), "magma:linkmanagershow", _OnShow);  
    Event.observe(Proxy.GetEventSink(), "magma:linkmanagerhide", _OnHide); 
    Event.observe(Proxy.GetEventSink(), "magma:linkmanagerlicenseerror", _OnLicenseError); 
    Event.observe(Proxy.GetEventSink(), "magma:linkmanagererror", _OnError);
    Event.observe(Proxy.GetEventSink(), "magma:linkmanagermessage", _OnMessage);  
    Event.observe(Proxy.GetEventSink(), "magma:linkmanagerpreparegui", _OnPrepareUI);
  }
  
  function _OnShow()
  {        
    Proxy.GetEventSink().fire(UPLATFORM.SHOWLINKMANAGEMENT);
  }
  
  function _OnHide()
  {    
    Proxy.GetEventSink().fire(UPLATFORM.HIDELINKMANAGEMENT);    
  }
  
  function _OnLicenseError(event)
  {
    alert("LinkManagement: license error"); // todo!
  }
  
  function _OnError(event)
  {
    alert("Linkmanagement: error"); // todo!
  }
  
  function _OnMessage(event)
  {
    _OnShow();
  }
  
  function _OnPrepareUI()
  {
    // Fired when an external linkmanagement request was received. This
    // is the place to prepare the user interface before actually executing
    // the received linkmanagement request.
    Proxy.Delta.Execute(new Hash({kernelaction: "delayedrequest"}));
  }
  
  function _Open(id)
  {    
    if ((id != null) && (typeof id == "string") && (id != "")) {
      Proxy.GetContext().UPlatform.ExecuteOpenDocumentRequest(
        new Hash({"action": "linkmanager", "id": id}));
    
      //Proxy.GetEventSink().fire(UPLATFORM.BEFOREOPENDOCUMENT, id);            
      //Proxy.Delta.Execute(new Hash({"action": "linkmanager", "id": id}));              
    }    
  }   
}

function KMUPlatformBookCompiler()
{
  var _available = false;
  var _documentId = null;
  var _initial = true;
  var _visible = false;
  
  this.Execute = _Execute;
  this.GetAvailable = _GetAvailable;
  this.GetDocumentId = _GetDocumentId;
  this.GetVisible = _GetVisible;
  _Create();
  
  function _Create() 
  {
    Event.observe(Proxy.GetEventSink(), "magma:bookcompileravailable", _OnAvailable);   
    Event.observe(Proxy.GetEventSink(), "magma:newdocument", _OnNewDocument);    
    Event.observe(Proxy.GetEventSink(), UPLATFORM.RELEASE.LIBRARYCHANGED, _OnUnavailable);
    Event.observe(Proxy.GetEventSink(), UPLATFORM.RELEASE.CHANGED, _OnUnavailable);
  }  
  
  function _GetAvailable()
  {
    return _available;
  }
  
  function _GetDocumentId()
  {
    return _documentId;
  }
  
  function _GetVisible()
  {
    return _visible;
  }
  
  function _OnNewDocument(event)
  {    
    if ((!event.memo.Parameters.json) && (_initial)) {  
      // Fire initial event to hide bookcompiler if unavailable
      _initial = false;
      Proxy.GetEventSink().fire(UPLATFORM.BOOKCOMPILER.UPDATED, {Available: false});         
    } else {      
      _DoBookVisibleUpdate(false);          
    }
  }
  
  function _OnAvailable(event)
  {  
    if ((_available)  && (!event.memo.Parameters.availablejson)) {
      _OnUnavailable();
    } else if (event.memo.Parameters.availablejson) {
      _available = true;      
      _documentId = event.memo.Parameters.documentid;      
      Proxy.GetEventSink().fire(UPLATFORM.BOOKCOMPILER.UPDATED, {Available: _available, Type: "bookcompiler"});     
    }
  }
  
  function _OnUnavailable()
  {
    if (_available) {
      _available = false;               
      Proxy.GetEventSink().fire(UPLATFORM.BOOKCOMPILER.UPDATED, {Available: _available});             
      _DoBookVisibleUpdate(false);             
    }
  }
  
  function _Execute(definition)
  {        
    if ((_available) && (typeof _documentId == "string")) {
      if (typeof definition != "string") {
        definition = "";
      }
      
      Proxy.GetContext().UPlatform.UpdateContent(new Hash({"action": "compilebook", 
        "documentid": _documentId, "definitionid": definition}));              
      _DoBookVisibleUpdate(true);              
    }
  }
  
  function _DoBookVisibleUpdate(value)
  {
    if ((_visible) &&  (!value)) {
      _visible = false;      
      Proxy.GetEventSink().fire(UPLATFORM.BOOKCOMPILER.USEUPDATE, {Visible: _visible});        
    } else if ((!_visible) && (value)) {
      _visible = true;            
      Proxy.GetEventSink().fire(UPLATFORM.BOOKCOMPILER.USEUPDATE, {Visible: _visible});        
    }
  }
}

function KMUPlatformFavorites()
{
  this.Add = _Add;
  this.AddCurrent = _AddCurrent;
  this.Delete = _Delete;
  this.Update = _Update;
  this.Execute = _Execute;
  
  _Create();
  
  function _Create()
  {
    Event.observe(Proxy.GetEventSink(), "magma:favoriteslistupdated", _OnFavoritesUpdated); 
    Event.observe(Proxy.GetEventSink(), "magma:favoritesexternalselected", _OnExternalFavoriteSelected);    
    Event.observe(Proxy.GetEventSink(), "magma:newdocument", _OnNewDocument);
  }
  
  function _Add(id, type, title)
  {
    if (typeof type != "string") {
      type = "";
    }
    if (typeof title != "string") {
      title = "";
    }    
  
    if (typeof id == "string") {
      Proxy.Delta.Execute(new Hash({"action": "addfav", "id": escape(id), "favtype": type, "title": escape(title)}));  
    }
  }   
  
  function _AddCurrent()
  {    
    var currentdocument = UPlatform.CurrentDocument();
    if (currentdocument) {
      _Add(currentdocument.Id);
    }
  }
  
  function _Delete(id)
  {
    if ((id != null) && (typeof id == "string")) {
      Proxy.Delta.Execute(new Hash({"action": "deletefav", "id": id}));      
    }
  }
  
  function _Update(id, title)
  {
    if ((typeof id == "string") && (id != "")) {
      if (typeof title != "string") {
        title = "";      
      }      
      Proxy.Delta.Execute(new Hash({"action": "updatefav", "id": id, "title": escape(title)}));
    }
  }
  
  function _Execute(id)
  {
    if ((id != null) && (typeof id == "string")) {
      Proxy.GetContext().UPlatform.ExecuteOpenDocumentRequest(new Hash({"action": "usefav", "id": id}));
      //Proxy.Delta.Execute(new Hash({"action": "usefav", "id": id}));      
    }  
  }
  
  function _OnFavoritesUpdated(event)
  { 
    if (UPlatform.CurrentDocument() != null) {  
      UPlatform.CurrentDocument().IsFavorite = event.memo.Parameters.currentdocumentisfavorite;
      _FireCurrentDocumentUpdateEvent(true, event.memo.Parameters.currentdocumentisfavorite);    
    }
    Proxy.GetEventSink().fire(UPLATFORM.FAVORITESUPDATED);  
  }
  
  function _OnExternalFavoriteSelected(event)
  {
    if ((event.memo.HasData) && (event.memo.Source) && (event.memo.Id)) {      
      var datavalue = event.memo.Source.$(event.memo.Id);            
      if (datavalue) {
        UPlatform.OpenExternal(datavalue.innerHTML);
      }
    }  
  }
  
  function _OnNewDocument(event)
  {    
    if (event.memo.Parameters.json) {          
      _FireCurrentDocumentUpdateEvent(true, event.memo.Parameters.json.IsFavorite);
    } else {    
      _FireCurrentDocumentUpdateEvent(false, false);
    }
  }
  
  function _FireCurrentDocumentUpdateEvent(isDocument, isFavorite)
  {      
    Proxy.GetEventSink().fire(UPLATFORM.FAVORITEDOCUMENTUPDATED, {"IsDocument": isDocument, "IsFavorite": isFavorite});
  }
}

function KMUPlatformHistory()
{
  this.Next = _Next;
  this.Previous = _Previous;  
  this.NavigateNext = _NavigateNext;
  this.NavigatePrevious = _NavigatePrevious;
  
  _Create();  
     
  function _Create()
  {
    Event.observe(Proxy.GetEventSink(), "magma:historyupdated", _OnHistoryUpdated);
  }  
  
  function _OnHistoryUpdated(event)
  {
    var frame = Proxy.GetContext();
    if (frame) {      
      frame.History.Next = event.memo.Parameters.nextjson;
      frame.History.Previous = event.memo.Parameters.previousjson;
      Proxy.GetEventSink().fire(UPLATFORM.HISTORYUPDATED, frame.History);
    }
  }

  function _Next()
  {
    var frame = Proxy.GetContext();
    if ((frame) && (frame.History) && (frame.History.Next)) {
      return frame.History.Next;
    } else {
      return null;
    }
  }
  
  function _Previous()
  {
    var frame = Proxy.GetContext();
    if ((frame) && (frame.History) && (frame.History.Previous)) {
      return frame.History.Previous;
    } else {
      return null;
    }  
  }  
  
  function _NavigateNext()
  {
    if (_Next() != null) {     
      Proxy.Delta.Execute(new Hash({"upaction": "nextlocation"}));              
    }    
  }
  
  function _NavigatePrevious()
  {
    if (_Previous() != null) {      
      Proxy.Delta.Execute(new Hash({"upaction": "previouslocation"}));              
    }  
  }  
}

function KMUPlatformFeedBack()
{
  this.Submit = _Submit;  
  
  function _Submit(data, options)
  {
    var form = null;
    var values = null;
    
    if ((Object.isUndefined(options)) || (options == null)) {
      options = {};
    }
    
    if (Object.isString(data)) {
      // data contains serialized query string
      values = data;
    } else if ((Object.isElement(data)) && (data.getElements)) {
      // data contains form that needs to be serialized
      values = Form.serializeElements(data.getElements());
      form = data;
    }
    
    if ((Object.isString(values)) && (!values.blank())) {
      if (!Object.isString(options.Id)) {
        options.Id = ""; // will use default settings
      }
      
      var list = new Hash({ sid: Proxy.GetValues().User.Sid, settingsid: options.Id,
        kmmagmaplatformrequesttype: "feedbackajax" });			 	  
      try {
				new Ajax.Request(Proxy.GetValues().Application.Module,
				{ method: 'post',
					evalJSON: true,
					parameters: list.toQueryString() + "&" + values,
					onSuccess: function(result) { _OnExecuteSuccess(form, result, options.OnSuccess, options.OnFailure); },			
					onFailure: function() { _OnExecuteFailure(form, escape("AJAX failure"), options.OnFailure); }
				});					
			} catch(ex) {
			  _OnExecuteFailure(form, "Exception: " + escape(ex.message), options.OnFailure);
			}            
    }    
  }
  
  function _OnExecuteSuccess(form, result, callBackSuccess, callBackFailure)
  {
    if (result) { 
      if ((result.responseJSON) && (result.responseJSON.Success)) {           
        if (Object.isElement(form)) {
          // clear form and errors          
          Form.reset(form);
          _ClearFormErrors(form);
        }
      
        if (Object.isFunction(callBackSuccess)) {
          callBackSuccess(result, form);
        }
      } else {
        _OnExecuteFailure(form, result, callBackFailure);
      }
    }
  }
  
  function _OnExecuteFailure(form, error, callBack)
  {
    if ((Object.isElement(form)) && (error)) {
      // Clear old errors
      _ClearFormErrors(form);
    
      // Add errors to form
      if (Object.isString(error)) {
        _DisplayFormError(form, error);
      } else if ((error.responseJSON) && (error.responseJSON.Error) && (error.responseJSON.Error.List)) {
        _DisplayFormError(form, error.responseJSON.Error.Text);
        
        // Iterate array of errors
        error.responseJSON.Error.List.each(function(item) {
          var field = form.ownerDocument.getElementById(item.Id + "_error");
          if (Object.isElement(field)) {
            if (!Element.hasClassName("error_message_field")) {
              Element.addClassName("error_message_field");
            }
            field.innerHTML = unescape(item.Text);
            Element.show(field);
          }        
        });
      }
    }
    
    if (Object.isFunction(callBack)) {
      callBack(error, form);
    }
  }
  
  function _DisplayFormError(form, error)
  {
    if ((Object.isElement(form)) && (Object.isString(error)) && (!error.blank())) {
      var field = form.ownerDocument.getElementById("errormessage");
      if (Object.isElement(field)) {
        field.innerHTML = unescape(error);
        Element.show(field);
      }
    }
  }
  
  function _ClearFormErrors(form)
  {    
    if (Object.isElement(form)) {
      var field = form.ownerDocument.getElementById("errormessage");
      if (Object.isElement(field)) {
        field.innerHTML = "";
        Element.hide(field);
      }
    
      var list = form.select(".error_message_field");                           
      list.each(function(field) {       
        field.innerHTML = "";
        Element.hide(field);
      });           
    }
  }
}

function KMUPlatformRelease()
{
  var _lastError = "";

  this.LastError = _lastError;
  this.GetValues = _getValues;
  this.UpdateValues = _updateValues;
  this.Select = _select;
  this.SelectLibrary = _selectLibrary;  
  this.CurrentRelease = _currentRelease;  
  this.CurrentLibrary = _currentLibrary;
  this.LibraryById = _libraryById;

  _Create();
     
  function _Create()
  {       
    var si = Proxy.GetStartupInfo();
    _valuesReceived(si);        
    Event.observe(Proxy.GetEventSink(), "magma:librarychanged", _OnLibraryChanged);    
  }
  
  function _OnLibraryChanged(event)
  {                
    _valuesReceived(event.memo.Parameters.releasejson);        
    _FireLibraryChanged(true, event.memo.Parameters);
    
    /*if (event.memo.Parameters.bookwillopenjson) {
      // Happens when library was changed caused by opening a new book            
      _FireLibraryChanged(true);
    }*/
  }

  function _FireLibraryChanged(indirect, parameters)
  {
    if (typeof parameters == "undefined") {
      parameters = null;
    }
    
    Proxy.GetEventSink().fire(UPLATFORM.RELEASE.LIBRARYCHANGED, 
      {Release: _currentRelease(), InDirect: indirect, Parameters: parameters});
  }
  
  function _getValues()
  {
    var frame = Proxy.GetContext();
    if ((frame) && (frame.ReleaseValues)) {
      return frame.ReleaseValues;
    } else {
      return null;
    }  
  }
  
  function _updateValues()
  {
    var list = new Hash({ "sid": Proxy.GetValues().User.Sid, 
      "kmmagmaplatformrequesttype": "releaseinfo"});	
 
    try { 
    	new Ajax.Request(Proxy.GetValues().Application.Module,
    	{ method: 'post',
        evalJSON: true,
    		parameters: list.toQueryString(),
    		onSuccess: function(result) {
          _valuesReceived(result.responseJSON);
          Proxy.GetEventSink().fire(UPLATFORM.RELEASE.VALUESUPDATED);  
        },			
    	  onFailure: function(value) {			  	  				
          Proxy.GetEventSink().fire(UPLATFORM.RELEASE.VALUESUPDATED);     
      	}
    	});		  
    } catch(ex) {
      Proxy.GetEventSink().fire(UPLATFORM.RELEASE.VALUESUPDATED);  
    }   
  }
  
  function _valuesReceived(newValues)
  {  
    if ((newValues) && (newValues.Release != null)) {  
      var frame = Proxy.GetContext();
      if ((frame) && (!Object.isUndefined(frame.ReleaseValues))) {        
        frame.ReleaseValues = {Release: newValues.Release};        
      } 
    }
  }  
  
  function _select(id)
  {
    if ((id != null) && (typeof id == "string")) {
      var list = new Hash({ "sid": Proxy.GetValues().User.Sid,
        "id": id, "ajax": true, "kmmagmaplatformrequesttype": "changerelease"});	
   
      try { 
      	new Ajax.Request(Proxy.GetValues().Application.Module,
      	{ method: 'post',
          evalJSON: true,
      		parameters: list.toQueryString(),
      		onSuccess: function(result) {
            if (result.responseJSON.Id) {
              _lastError = result.responseJSON.Parameters.errortext;              
              Proxy.GetEventSink().fire(UPLATFORM.RELEASE.CHANGEFAILED, _lastError);  
            } else {              
              _valuesReceived(result.responseJSON);              
              Proxy.GetEventSink().fire(UPLATFORM.RELEASE.CHANGED);               
            }
          },			
      	  onFailure: function(value) {			  	  				
            _lastError = value;            
            Proxy.GetEventSink().fire(UPLATFORM.RELEASE.CHANGEFAILED, _lastError);   
        	}
      	});		  
      } catch(ex) {
        _lastError = ex.message;
        Proxy.GetEventSink().fire(UPLATFORM.RELEASE.CHANGEFAILED, _lastError);  
      } 
    }
  }
  
  function _selectLibrary(id)
  {
    if ((id != null) && (typeof id == "string")) {
      var list = new Hash({ "sid": Proxy.GetValues().User.Sid,
        "id": id, "ajax": true, "kmmagmaplatformrequesttype": "changelibrary"});	
   
      try { 
      	new Ajax.Request(Proxy.GetValues().Application.Module,
      	{ method: 'post',
          evalJSON: true,
      		parameters: list.toQueryString(),
      		onSuccess: function(result) {
            if (result.responseJSON.Id) {
              _lastError = result.responseJSON.Parameters.errortext;              
              Proxy.GetEventSink().fire(UPLATFORM.RELEASE.LIBRARYCHANGEFAILED, _lastError);  
            } else {                                        
              _valuesReceived(result.responseJSON);              
              _FireLibraryChanged(false, null);
            }
          },			
      	  onFailure: function(value) {			  	  				
            _lastError = value;            
            Proxy.GetEventSink().fire(UPLATFORM.RELEASE.LIBRARYCHANGEFAILED, _lastError);   
        	}
      	});		  
      } catch(ex) {
        _lastError = ex.message;
        Proxy.GetEventSink().fire(UPLATFORM.RELEASE.LIBRARYCHANGEFAILED, _lastError);  
      } 
    }
  } 

  function _libraryById(id)  
  {    
    if ((id != null) && (typeof id == "string")) {
      var result = null;
      _getValues().Release.Library.List.each(function(library) {        
        if (library.Id == id) { 
          result = library;
          $break;          
        }
      });
      return result;
    } else {
      return null;
    }
  }
  
  function _currentLibrary()
  {
    return _libraryById(_getValues().Release.Library.Id);    
  }
  
  function _currentRelease()
  {
    return _getValues().Release;
  }
}