/*
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.IO.IsolatedStorage;
using System.Windows.Resources;
using System.Windows.Interop;
using System.Runtime.Serialization.Json;
using System.IO;
using System.ComponentModel;
using System.Xml.Linq;
using WPCordovaClassLib.Cordova.Commands;
using System.Diagnostics;
using System.Text;
using WPCordovaClassLib.Cordova;
using System.Threading;
using Microsoft.Phone.Shell;
using WPCordovaClassLib.Cordova.JSON;
using WPCordovaClassLib.CordovaLib;



namespace WPCordovaClassLib
{
    public partial class CordovaView : UserControl
    {

        /// <summary>
        /// Indicates whether web control has been loaded and no additional initialization is needed.
        /// Prevents data clearing during page transitions.
        /// </summary>
        private bool IsBrowserInitialized = false;

        /// <summary>
        /// Set when the user attaches a back button handler inside the WebBrowser
        /// </summary>
        private bool OverrideBackButton = false;

        /// <summary>
        /// Sentinel to keep track of page changes as a result of the hardware back button
        /// Set to false when the back-button is pressed, which calls js window.history.back()
        /// If the page changes as a result of the back button the event is cancelled.
        /// </summary>
        private bool PageDidChange = false;

        private static string AppRoot = "/app/";


        /// <summary>
        /// Handles native api calls
        /// </summary>
        private NativeExecution nativeExecution;

        protected BrowserMouseHelper bmHelper;

        private ConfigHandler configHandler;

        private Dictionary<string, IBrowserDecorator> browserDecorators;

        public System.Windows.Controls.Grid _LayoutRoot
        {
            get
            {
                return ((System.Windows.Controls.Grid)(this.FindName("LayoutRoot")));
            }
        }

        public WebBrowser Browser
        {
            get
            {
                return CordovaBrowser;
            }
        }

        /*
         * Setting StartPageUri only has an effect if called before the view is loaded.
         **/
        protected Uri _startPageUri = null;
        public Uri StartPageUri
        {
            get
            {
                if (_startPageUri == null)
                {
                    // default
                    return new Uri(AppRoot + "www/index.html", UriKind.Relative);
                }
                else
                {
                    return _startPageUri;
                }
            }
            set
            {
                if (!this.IsBrowserInitialized)
                {
                    _startPageUri = value;
                }
            }
        }

        public CordovaView()
        {

            InitializeComponent();

            if (DesignerProperties.IsInDesignTool)
            {
                return;
            }


            StartupMode mode = PhoneApplicationService.Current.StartupMode;

            if (mode == StartupMode.Launch)
            {
                PhoneApplicationService service = PhoneApplicationService.Current;
                service.Activated += new EventHandler<Microsoft.Phone.Shell.ActivatedEventArgs>(AppActivated);
                service.Launching += new EventHandler<LaunchingEventArgs>(AppLaunching);
                service.Deactivated += new EventHandler<DeactivatedEventArgs>(AppDeactivated);
                service.Closing += new EventHandler<ClosingEventArgs>(AppClosing);
            }
            else
            {

            }

            configHandler = new ConfigHandler();
            configHandler.LoadAppPackageConfig();

            if (configHandler.ContentSrc != null)
            {
                if (Uri.IsWellFormedUriString(configHandler.ContentSrc, UriKind.Absolute))
                {
                    this.StartPageUri = new Uri(configHandler.ContentSrc, UriKind.Absolute);
                }
                else
                {
                    this.StartPageUri = new Uri(AppRoot + "www/" + configHandler.ContentSrc, UriKind.Relative);
                }
            }


            browserDecorators = new Dictionary<string, IBrowserDecorator>();

            // initializes native execution logic
            nativeExecution = new NativeExecution(ref this.CordovaBrowser);
            bmHelper = new BrowserMouseHelper(ref this.CordovaBrowser);

            CreateDecorators();
        }

        /*
         *   browserDecorators are a collection of plugin-like classes (IBrowserDecorator) that add some bit of functionality to the browser.
         *   These are somewhat different than plugins in that they are usually not async and patch a browser feature that we would
         *   already expect to have.  Essentially these are browser polyfills that are patched from the outside in.
         * */
        void CreateDecorators()
        {
            XHRHelper xhrProxy = new XHRHelper();
            xhrProxy.Browser = CordovaBrowser;
            browserDecorators.Add("XHRLOCAL", xhrProxy);

            OrientationHelper orientHelper = new OrientationHelper();
            orientHelper.Browser = CordovaBrowser;
            browserDecorators.Add("Orientation", orientHelper);

            DOMStorageHelper storageHelper = new DOMStorageHelper();
            storageHelper.Browser = CordovaBrowser;
            browserDecorators.Add("DOMStorage", storageHelper);

            ConsoleHelper console = new ConsoleHelper();
            console.Browser = CordovaBrowser;
            browserDecorators.Add("ConsoleLog", console);

        }



        void AppClosing(object sender, ClosingEventArgs e)
        {
            //Debug.WriteLine("AppClosing");
        }

        void AppDeactivated(object sender, DeactivatedEventArgs e)
        {
            Debug.WriteLine("INFO: AppDeactivated");

            try
            {
                CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('pause');" });
            }
            catch (Exception)
            {
                Debug.WriteLine("ERROR: Pause event error");
            }
        }

        void AppLaunching(object sender, LaunchingEventArgs e)
        {
            //Debug.WriteLine("INFO: AppLaunching");
        }

        void AppActivated(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
        {
            Debug.WriteLine("INFO: AppActivated");
            try
            {
                CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('resume');" });
            }
            catch (Exception)
            {
                Debug.WriteLine("ERROR: Resume event error");
            }
        }

        void GapBrowser_Loaded(object sender, RoutedEventArgs e)
        {
            if (DesignerProperties.IsInDesignTool)
            {
                return;
            }

            // prevents refreshing web control to initial state during pages transitions
            if (this.IsBrowserInitialized) return;

            try
            {

                // Before we possibly clean the ISO-Store, we need to grab our generated UUID, so we can rewrite it after.
                string deviceUUID = "";

                using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    try
                    {
                        IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Open, FileAccess.Read, appStorage);

                        using (StreamReader reader = new StreamReader(fileStream))
                        {
                            deviceUUID = reader.ReadLine();
                        }
                    }
                    catch (Exception /*ex*/)
                    {
                        deviceUUID = Guid.NewGuid().ToString();
                        Debug.WriteLine("Updating IsolatedStorage for APP:DeviceID :: " + deviceUUID);
                        IsolatedStorageFileStream file = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Create, FileAccess.Write, appStorage);
                        using (StreamWriter writeFile = new StreamWriter(file))
                        {
                            writeFile.WriteLine(deviceUUID);
                            writeFile.Close();
                        }
                    }
                }

                StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("CordovaSourceDictionary.xml", UriKind.Relative));

                if (streamInfo != null)
                {
                    StreamReader sr = new StreamReader(streamInfo.Stream);
                    //This will Read Keys Collection for the xml file

                    XDocument document = XDocument.Parse(sr.ReadToEnd());

                    var files = from results in document.Descendants("FilePath")
                                select new
                                {
                                    path = (string)results.Attribute("Value")
                                };
                    StreamResourceInfo fileResourceStreamInfo;

                    using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                    {

                        foreach (var file in files)
                        {
                            fileResourceStreamInfo = Application.GetResourceStream(new Uri(file.path, UriKind.Relative));

                            if (fileResourceStreamInfo != null)
                            {
                                using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
                                {
                                    byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);

                                    string strBaseDir = AppRoot + file.path.Substring(0, file.path.LastIndexOf(System.IO.Path.DirectorySeparatorChar));

                                    if (!appStorage.DirectoryExists(strBaseDir))
                                    {
                                        Debug.WriteLine("INFO: Creating Directory :: " + strBaseDir);
                                        appStorage.CreateDirectory(strBaseDir);
                                    }

                                    // This will truncate/overwrite an existing file, or
                                    using (IsolatedStorageFileStream outFile = appStorage.OpenFile(AppRoot + file.path, FileMode.Create))
                                    {
                                        Debug.WriteLine("INFO: Writing data for " + AppRoot + file.path + " and length = " + data.Length);
                                        using (var writer = new BinaryWriter(outFile))
                                        {
                                            writer.Write(data);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                Debug.WriteLine("ERROR: Failed to write file :: " + file.path + " did you forget to add it to the project?");
                            }
                        }
                    }
                }

                CordovaBrowser.Navigate(StartPageUri);
                IsBrowserInitialized = true;
                AttachHardwareButtonHandlers();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("ERROR: Exception in GapBrowser_Loaded :: {0}", ex.Message);
            }
        }

        void AttachHardwareButtonHandlers()
        {
            PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
            if (frame != null)
            {
                PhoneApplicationPage page = frame.Content as PhoneApplicationPage;

                if (page != null)
                {
                    page.BackKeyPress += new EventHandler<CancelEventArgs>(page_BackKeyPress);
                    // CB-2347 -jm
                    string fullscreen = configHandler.GetPreference("fullscreen");
                    bool bFullScreen = false;
                    if (bool.TryParse(fullscreen, out bFullScreen) && bFullScreen)
                    {
                        SystemTray.SetIsVisible(page, false);
                    }
                }
            }
        }

        void page_BackKeyPress(object sender, CancelEventArgs e)
        {

            if (OverrideBackButton)
            {
                try
                {
                    CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('backbutton', {}, true);" });
                    e.Cancel = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception while invoking backbutton into cordova view: " + ex.Message);
                }
            }
            else
            {
                try
                {
                    PageDidChange = false;

                    Uri uriBefore = this.Browser.Source;
                    // calling js history.back with result in a page change if history was valid.
                    CordovaBrowser.InvokeScript("eval", new string[] { "(function(){window.history.back();})()" });

                    Uri uriAfter = this.Browser.Source;

                    e.Cancel = PageDidChange || (uriBefore != uriAfter);
                }
                catch (Exception)
                {
                    e.Cancel = false; // exit the app ... ?
                }
            }
        }

        void GapBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            string nativeReady = "(function(){ window.setTimeout(function(){cordova.require('cordova/channel').onNativeReady.fire()},0) })();";

            try
            {
                CordovaBrowser.InvokeScript("execScript", new string[] { nativeReady });
            }
            catch (Exception /*ex*/)
            {
                Debug.WriteLine("Error calling js to fire nativeReady event. Did you include cordova.js in your html script tag?");
            }

            if (this.CordovaBrowser.Opacity < 1)
            {
                this.CordovaBrowser.Opacity = 1;
                RotateIn.Begin();
            }
        }


        void GapBrowser_Navigating(object sender, NavigatingEventArgs e)
        {
            if (!configHandler.URLIsAllowed(e.Uri.ToString()))
            {
                e.Cancel = true;
                return;
            }

            this.PageDidChange = true;
            // Debug.WriteLine("GapBrowser_Navigating to :: " + e.Uri.ToString());
            this.nativeExecution.ResetAllCommands();

            // TODO: check whitelist / blacklist
            // NOTE: Navigation can be cancelled by setting :        e.Cancel = true;
        }

        /*
         *  This method does the work of routing commands
         *  NotifyEventArgs.Value contains a string passed from JS
         *  If the command already exists in our map, we will just attempt to call the method(action) specified, and pass the args along
         *  Otherwise, we create a new instance of the command, add it to the map, and call it ...
         *  This method may also receive JS error messages caught by window.onerror, in any case where the commandStr does not appear to be a valid command
         *  it is simply output to the debugger output, and the method returns.
         *
         **/
        void GapBrowser_ScriptNotify(object sender, NotifyEventArgs e)
        {
            string commandStr = e.Value;
            string commandName = commandStr.Split('/').FirstOrDefault();

            if (browserDecorators.ContainsKey(commandName))
            {
                browserDecorators[commandName].HandleCommand(commandStr);
                return;
            }

            CordovaCommandCall commandCallParams = CordovaCommandCall.Parse(commandStr);

            if (commandCallParams == null)
            {
                // ERROR
                Debug.WriteLine("ScriptNotify :: " + commandStr);
            }
            else if (commandCallParams.Service == "CoreEvents")
            {
                switch (commandCallParams.Action.ToLower())
                {
                    case "overridebackbutton":
                        string arg0 = JsonHelper.Deserialize<string[]>(commandCallParams.Args)[0];
                        this.OverrideBackButton = (arg0 != null && arg0.Length > 0 && arg0.ToLower() == "true");
                        break;
                }
            }
            else
            {
                if (configHandler.IsPluginAllowed(commandCallParams.Service))
                {
                    nativeExecution.ProcessCommand(commandCallParams);
                }
                else
                {
                    Debug.WriteLine("Error::Plugin not allowed in config.xml. " + commandCallParams.Service);
                }
            }
        }

        public void LoadPage(string url)
        {
            try
            {
                Uri newLoc = new Uri(url,UriKind.RelativeOrAbsolute);
                CordovaBrowser.Navigate(newLoc);
            }
            catch(Exception)
            {

            }
        }

        private void GapBrowser_Unloaded(object sender, RoutedEventArgs e)
        {

        }

        private void GapBrowser_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
        {
            Debug.WriteLine("GapBrowser_NavigationFailed :: " + e.Uri.ToString());
        }

        private void GapBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            Debug.WriteLine("GapBrowser_Navigated :: " + e.Uri.ToString());
            foreach (IBrowserDecorator iBD in browserDecorators.Values)
            {
                iBD.InjectScript();
            }
        }


    }
}
