Merge pull request #6 from bennmapes/create_script

Scripts for cordova-cli
diff --git a/templates/standalone/cordovalib/Commands/AudioPlayer.cs b/templates/standalone/cordovalib/Commands/AudioPlayer.cs
index ffc6a94..a83be5b 100644
--- a/templates/standalone/cordovalib/Commands/AudioPlayer.cs
+++ b/templates/standalone/cordovalib/Commands/AudioPlayer.cs
@@ -23,6 +23,7 @@
 using Microsoft.Xna.Framework.Media;
 using Microsoft.Phone.Controls;
 using System.Diagnostics;
+using System.Windows.Resources;
 
 namespace WPCordovaClassLib.Cordova.Commands
 {
@@ -57,7 +58,7 @@
         private const int MediaErrorStopState = 8;
 
         //TODO: get rid of this callback, it should be universal
-        private const string CallbackFunction = "CordovaMediaonStatus";
+        //private const string CallbackFunction = "CordovaMediaonStatus";
 
         #endregion
 
@@ -132,7 +133,6 @@
         /// </summary>
         public void Dispose()
         {
-            Debug.WriteLine("Dispose :: " + this.audioFile);
             if (this.player != null)
             {
                 this.stopPlaying();
@@ -147,6 +147,33 @@
             this.FinalizeXnaGameLoop();
         }
 
+        private void InvokeCallback(int message, string value, bool removeHandler)
+        {
+            string args = string.Format("('{0}',{1},{2});", this.id, message, value);
+            string callback = @"(function(id,msg,value){
+                try {
+                    if (msg == Media.MEDIA_ERROR) {
+                        value = {'code':value};
+                    }
+                    Media.onStatus(id,msg,value);
+                }
+                catch(e) {
+                    console.log('Error calling Media.onStatus :: ' + e);
+                }
+            })" + args;
+            this.handler.InvokeCustomScript(new ScriptCallback("eval", new string[] { callback }), false);
+        }
+
+        private void InvokeCallback(int message, int value, bool removeHandler)
+        {
+            InvokeCallback(message, value.ToString(), removeHandler);
+        }
+
+        private void InvokeCallback(int message, double value, bool removeHandler)
+        {
+            InvokeCallback(message, value.ToString(), removeHandler);
+        }
+
         /// <summary>
         /// Starts recording, data is stored in memory
         /// </summary>
@@ -155,7 +182,7 @@
         {
             if (this.player != null)
             {
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorPlayModeSet),false);
+                InvokeCallback(MediaError, MediaErrorPlayModeSet, false);
             }
             else if (this.recorder == null)
             {
@@ -175,13 +202,14 @@
                 }
                 catch (Exception)
                 {
-                    this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingRecording),false);
+                    InvokeCallback(MediaError, MediaErrorStartingRecording, false);
+                    //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingRecording),false);
                 }
             }
             else
             {
-
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorAlreadyRecording),false);
+                InvokeCallback(MediaError, MediaErrorAlreadyRecording, false);
+                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorAlreadyRecording),false);
             }
         }
 
@@ -223,12 +251,13 @@
         {
             if (this.recorder != null)
             {
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorRecordModeSet),false);
+                InvokeCallback(MediaError, MediaErrorRecordModeSet, false);
+                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorRecordModeSet),false);
                 return;
             }
 
 
-            if (this.player == null || this.player.Source == null || this.player.Source.AbsolutePath.LastIndexOf(filePath) < 0)
+            if (this.player == null || this.player.Source.AbsolutePath.LastIndexOf(filePath) < 0)
             {
                 try
                 {
@@ -243,7 +272,6 @@
                             if (grid != null)
                             {
 
-                                //Microsoft.Xna.Framework.Media.MediaPlayer.Play(
                                 this.player = grid.FindName("playerMediaElement") as MediaElement;
                                 if (this.player == null) // still null ?
                                 {
@@ -276,6 +304,37 @@
                     {
                         using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
                         {
+                            if (!isoFile.FileExists(filePath))
+                            {
+                                // try to unpack it from the dll into isolated storage
+                                StreamResourceInfo fileResourceStreamInfo = Application.GetResourceStream(new Uri(filePath, UriKind.Relative));
+                                if (fileResourceStreamInfo != null)
+                                {
+                                    using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
+                                    {
+                                        byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);          
+
+                                        string[] dirParts = filePath.Split('/');
+                                        string dirName = "";
+                                        for (int n = 0; n < dirParts.Length - 1; n++)
+                                        {
+                                            dirName += dirParts[n] + "/";
+                                        }
+                                        if (!isoFile.DirectoryExists(dirName))
+                                        {
+                                            isoFile.CreateDirectory(dirName);
+                                        }
+
+                                        using (IsolatedStorageFileStream outFile = isoFile.OpenFile(filePath, FileMode.Create))
+                                        {
+                                            using (BinaryWriter writer = new BinaryWriter(outFile))
+                                            {
+                                                writer.Write(data);
+                                            }
+                                        }
+                                    }
+                                }
+                            }
                             if (isoFile.FileExists(filePath))
                             {
                                 using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, isoFile))
@@ -285,10 +344,9 @@
                             }
                             else
                             {
-                                Debug.WriteLine("Error: source doesn't exist :: " + filePath);
-                                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, 1),false);
+                                InvokeCallback(MediaError, MediaErrorPlayModeSet, false);
+                                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, 1), false);
                                 return;
-                                //throw new ArgumentException("Source doesn't exist");
                             }
                         }
                     }
@@ -296,8 +354,9 @@
                 }
                 catch (Exception e)
                 {
-                    Debug.WriteLine("Error: " + e.Message);
-                    this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingPlayback),false);
+                    Debug.WriteLine("Error in AudioPlayer::startPlaying : " + e.Message);
+                    InvokeCallback(MediaError, MediaErrorStartingPlayback, false);
+                    //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingPlayback),false);
                 }
             }
             else
@@ -309,7 +368,8 @@
                 }
                 else
                 {
-                    this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorResumeState),false);
+                    InvokeCallback(MediaError, MediaErrorResumeState, false);
+                    //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorResumeState),false);
                 }
             }
         }
@@ -322,7 +382,8 @@
             if (this.player != null)
             {
                 this.duration = this.player.NaturalDuration.TimeSpan.TotalSeconds;
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaDuration, this.duration),false);
+                InvokeCallback(MediaDuration, this.duration, false);
+                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaDuration, this.duration),false);
                 if (!this.prepareOnly)
                 {
                     this.player.Play();
@@ -350,7 +411,8 @@
         private void MediaFailed(object sender, RoutedEventArgs arg)
         {
             player.Stop();
-            this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError.ToString(), "Media failed"),false);
+            InvokeCallback(MediaError, MediaErrorStartingPlayback, false);
+            //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError.ToString(), "Media failed"),false);
         }
 
         /// <summary>
@@ -363,7 +425,8 @@
             {
                 TimeSpan tsPos = new TimeSpan(0, 0, 0, 0, milliseconds);
                 this.player.Position = tsPos;
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaPosition, milliseconds / 1000.0f),false);
+                InvokeCallback(MediaPosition, milliseconds / 1000.0f, false);
+                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaPosition, milliseconds / 1000.0f),false);
             }
         }
 
@@ -391,7 +454,8 @@
             }
             else
             {
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorPauseState),false);
+                InvokeCallback(MediaError, MediaErrorPauseState, false);
+                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorPauseState),false);
             }
         }
 
@@ -465,7 +529,8 @@
         {
             if (this.state != state)
             {
-                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaState, state),false);
+                InvokeCallback(MediaState, state, false);
+                //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaState, state),false);
             }
 
             this.state = state;
@@ -523,7 +588,6 @@
             }
         }    
 
-
         #region Xna loop
         /// <summary>
         /// Special initialization required for the microphone: XNA game loop
diff --git a/templates/standalone/cordovalib/Commands/BaseCommand.cs b/templates/standalone/cordovalib/Commands/BaseCommand.cs
index f6e45da..237b72a 100644
--- a/templates/standalone/cordovalib/Commands/BaseCommand.cs
+++ b/templates/standalone/cordovalib/Commands/BaseCommand.cs
@@ -71,7 +71,7 @@
 
         }
 
-
+        [Obsolete]
         public void InvokeCustomScript(ScriptCallback script, bool removeHandler)
         {
             if (this.OnCustomScript != null)
@@ -111,6 +111,14 @@
         {
         }
 
+        /// <summary>
+        /// Occurs when the application is being loaded, and the config.xml has an autoload entry
+        /// </summary>    
+        public virtual void OnInit()
+        {
+
+        }
+
 
         /// <summary>
         /// Occurs when the application is being deactivated.
diff --git a/templates/standalone/cordovalib/CordovaCommandCall.cs b/templates/standalone/cordovalib/CordovaCommandCall.cs
index 084fd2c..a864fe6 100644
--- a/templates/standalone/cordovalib/CordovaCommandCall.cs
+++ b/templates/standalone/cordovalib/CordovaCommandCall.cs
@@ -64,7 +64,7 @@
 
             // sanity check for illegal names
             // was failing with ::
-            // CordovaCommandResult :: 1, Device1, {"status":1,"message":"{\"name\":\"XD.....
+            // 1, Device1, {"status":1,"message":"{\"name\":\"XD.....
             if (commandCallParameters.Service.IndexOfAny(new char[] { '@', ':', ',', '!', ' ' }) > -1)
             {
                 return null;
diff --git a/templates/standalone/cordovalib/CordovaView.xaml.cs b/templates/standalone/cordovalib/CordovaView.xaml.cs
index a6c4bce..f6584a8 100644
--- a/templates/standalone/cordovalib/CordovaView.xaml.cs
+++ b/templates/standalone/cordovalib/CordovaView.xaml.cs
@@ -161,7 +161,7 @@
 
         void AppClosing(object sender, ClosingEventArgs e)
         {
-            Debug.WriteLine("AppClosing");
+            //Debug.WriteLine("AppClosing");
         }
 
         void AppDeactivated(object sender, DeactivatedEventArgs e)
@@ -170,7 +170,7 @@
 
             try
             {
-                CordovaBrowser.InvokeScript("CordovaCommandResult", new string[] { "pause" });
+                CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('pause');" });
             }
             catch (Exception)
             {
@@ -180,7 +180,7 @@
 
         void AppLaunching(object sender, LaunchingEventArgs e)
         {
-            Debug.WriteLine("INFO: AppLaunching");
+            //Debug.WriteLine("INFO: AppLaunching");
         }
 
         void AppActivated(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
@@ -188,7 +188,7 @@
             Debug.WriteLine("INFO: AppActivated");
             try
             {
-                CordovaBrowser.InvokeScript("CordovaCommandResult", new string[] { "resume" });
+                CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('resume');" });
             }
             catch (Exception)
             {
@@ -332,7 +332,7 @@
             {
                 try
                 {
-                    CordovaBrowser.InvokeScript("CordovaCommandResult", new string[] { "backbutton" });
+                    CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('backbutton');" });
                     e.Cancel = true;
                 }
                 catch (Exception ex)
@@ -367,9 +367,9 @@
 
             try
             {
-                CordovaBrowser.InvokeScript("execScript", new string[] { nativeReady });
+                CordovaBrowser.InvokeScript("eval", new string[] { nativeReady });
             }
-            catch (Exception /*ex*/)
+            catch (Exception ex)
             {
                 Debug.WriteLine("Error calling js to fire nativeReady event. Did you include cordova-x.x.x.js in your html script tag?");
             }
diff --git a/templates/standalone/cordovalib/NativeExecution.cs b/templates/standalone/cordovalib/NativeExecution.cs
index 9459ffc..25efd01 100644
--- a/templates/standalone/cordovalib/NativeExecution.cs
+++ b/templates/standalone/cordovalib/NativeExecution.cs
@@ -61,15 +61,23 @@
             CommandFactory.ResetAllCommands();
         }
 
+        public void AutoLoadCommand(string commandService)
+        {
+            BaseCommand bc = CommandFactory.CreateByServiceName(commandService);
+            if (bc != null)
+            {
+                bc.OnInit();
+            }
+
+        }
+
         /// <summary>
         /// Executes command and returns result back.
         /// </summary>
         /// <param name="commandCallParams">Command to execute</param>
-        
         public void ProcessCommand(CordovaCommandCall commandCallParams)
         {
 
-            
             if (commandCallParams == null)
             {
                 throw new ArgumentNullException("commandCallParams");
@@ -90,7 +98,6 @@
                     this.OnCommandResult(commandCallParams.CallbackId, res);
                 };
 
-                bc.OnCommandResult -= OnCommandResultHandler;
                 bc.OnCommandResult += OnCommandResultHandler;
 
                 EventHandler<ScriptCallback> OnCustomScriptHandler = delegate(object o, ScriptCallback script)
@@ -98,14 +105,12 @@
                     this.InvokeScriptCallback(script);
                 };
 
-                bc.OnCustomScript -= OnCustomScriptHandler;
+
                 bc.OnCustomScript += OnCustomScriptHandler;
 
-                // TODO: alternative way is using thread pool (ThreadPool.QueueUserWorkItem) instead of 
-                // new thread for every command call; but num threads are not sufficient - 2 threads per CPU core
-
-                Thread thread = new Thread(func =>
+                ThreadStart methodInvocation = () =>
                 {
+
                     try
                     {
                         bc.InvokeMethodNamed(commandCallParams.Action, commandCallParams.Args);
@@ -122,9 +127,20 @@
 
                         return;
                     }
-                });
+                };
 
-                thread.Start();
+                if ((bc is File) || (bc is Accelerometer))
+                {
+                    // Due to some issues with the IsolatedStorage in current version of WP8 SDK we have to run all File Api commands synchronously.
+                    // TODO: test this in WP8 RTM
+                    methodInvocation.Invoke();
+                }
+                else
+                {
+                    new Thread(methodInvocation).Start();
+                }
+
+                    
             }
             catch (Exception ex)
             {
@@ -160,21 +176,27 @@
 
             #endregion
 
-            string status = ((int)result.Result).ToString();
             string jsonResult = result.ToJSONString();
 
-            ScriptCallback scriptCallback = null;
+            string callback;
+            string args = string.Format("('{0}',{1});", callbackId, jsonResult);
 
-            if (String.IsNullOrEmpty(result.Cast))
+            if (result.Result == PluginResult.Status.NO_RESULT ||
+               result.Result == PluginResult.Status.OK)
             {
-                scriptCallback = new ScriptCallback("CordovaCommandResult", new string[] { status, callbackId, jsonResult });
+                callback = @"(function(callbackId,args) {
+                try { args.message = JSON.parse(args.message); } catch (ex) { }
+                cordova.callbackSuccess(callbackId,args);
+                })" + args;
             }
             else
             {
-                scriptCallback = new ScriptCallback("CordovaCommandResult", new string[] { status, callbackId, jsonResult, result.Cast });
+                callback = @"(function(callbackId,args) {
+                try { args.message = JSON.parse(args.message); } catch (ex) { }
+                cordova.callbackError(callbackId,args);
+                })" + args;
             }
-
-            this.InvokeScriptCallback(scriptCallback);
+            this.InvokeScriptCallback(new ScriptCallback("eval", new string[] { callback }));
 
         }
 
@@ -197,7 +219,6 @@
             //Debug.WriteLine("INFO:: About to invoke ::" + script.ScriptName + " with args ::" + script.Args[0]);
             this.webBrowser.Dispatcher.BeginInvoke((ThreadStart)delegate()
             {
-
                 try
                 {
                     //Debug.WriteLine("INFO:: InvokingScript::" + script.ScriptName + " with args ::" + script.Args[0]);
diff --git a/templates/standalone/cordovalib/PluginResult.cs b/templates/standalone/cordovalib/PluginResult.cs
index b887bb8..e6d0c56 100644
--- a/templates/standalone/cordovalib/PluginResult.cs
+++ b/templates/standalone/cordovalib/PluginResult.cs
@@ -68,8 +68,6 @@
 
         public Status Result { get; private set; }
         public string Message { get; set; }
-        public String Cast { get; private set; }
-
         public bool KeepCallback { get; set; }
 
         /// <summary>
@@ -103,21 +101,6 @@
             this.Message = JSON.JsonHelper.Serialize(message);
         }
 
-        /// <summary>
-        /// Creates new instance of the PluginResult class.
-        /// </summary>
-        /// <param name="status">Execution result</param>
-        /// <param name="message">The message</param>
-        /// <param name="cast">The cast parameter</param>
-        /// 
-        [Obsolete("Don't use Cast!!", false)]
-        public PluginResult(Status status, object message, string cast)
-        {
-            this.Result = status;
-            this.Message = JSON.JsonHelper.Serialize(message);
-            this.Cast = cast;
-        }
-
         public string ToJSONString()
         {
             string res = String.Format("\"status\":{0},\"message\":{1},\"keepCallback\":{2}",
@@ -132,21 +115,10 @@
 
         public string ToCallbackString(string callbackId, string successCallback, string errorCallback)
         {
-            //return String.Format("{0}('{1}',{2});", successCallback, callbackId, this.ToJSONString());
-
             if (this.IsSuccess)
             {
                 StringBuilder buf = new StringBuilder("");
-                if (this.Cast != null)
-                {
-                    Debug.WriteLine(callbackId + "this.Cast = " + this.Cast);
-                    buf.Append("var temp = " + this.Cast + "(" + this.ToJSONString() + ");\n");
-                    buf.Append(String.Format("{0}('{1}',temp);", successCallback, callbackId));
-                }
-                else
-                {
-                    buf.Append(String.Format("{0}('{1}',{2});", successCallback, callbackId, this.ToJSONString()));
-                }
+                buf.Append(String.Format("{0}('{1}',{2});", successCallback, callbackId, this.ToJSONString()));
                 return buf.ToString();
             }
             else