/*
    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.Globalization;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using WPCordovaClassLib.Cordova;
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>
        /// Sentinal 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 = "";


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

        protected BrowserMouseHelper bmHelper;

        private ConfigHandler configHandler;

        protected bool IsExiting = false;

        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;
                }
            }
        }

        /// <summary>
        /// Gets or sets whether to suppress bouncy scrolling of
        /// the WebBrowser control;
        /// </summary>
        public bool DisableBouncyScrolling
        {
            get;
            set;
        }

        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
            {

            }

            // initializes native execution logic
            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>();

            nativeExecution = new NativeExecution(ref this.CordovaBrowser);
            bmHelper = new BrowserMouseHelper(ref this.CordovaBrowser);

            ApplyConfigurationPreferences();

            CreateDecorators();
        }

        /// <summary>
        /// Applies configuration preferences. Only BackgroundColor+fullscreen is currently supported.
        /// </summary>
        private void ApplyConfigurationPreferences()
        {
            string bgColor = configHandler.GetPreference("backgroundcolor");

            if (!String.IsNullOrEmpty(bgColor))
            {
                try
                {
                    Browser.Background = new SolidColorBrush(ColorFromHex(bgColor));
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Unable to parse BackgroundColor value '{0}'. Error: {1}", bgColor, ex.Message);
                }
            }
        }

        /*
         *   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);

            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 because " + e.Reason);
            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 CordovaBrowser_Loaded(object sender, RoutedEventArgs e)
        {

            this.bmHelper.ScrollDisabled = this.DisableBouncyScrolling;

            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();
                        }
                    }
                }

                CordovaBrowser.Navigate(StartPageUri);
                IsBrowserInitialized = true;
                AttachHardwareButtonHandlers();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("ERROR: Exception in CordovaBrowser_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)
                {
                    Debug.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 CordovaBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            if (IsExiting)
            {
                // Special case, we navigate to about:blank when we are about to exit.
                IsolatedStorageSettings.ApplicationSettings.Save();
                Application.Current.Terminate();
                return;
            }

            Debug.WriteLine("CordovaBrowser_LoadCompleted");

            string version = "?";
            System.Windows.Resources.StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("VERSION", UriKind.Relative));
            if (streamInfo != null)
            {
                using(StreamReader sr = new StreamReader(streamInfo.Stream))
                {
                    version = sr.ReadLine();
                }
            }
            Debug.WriteLine("Apache Cordova native platform version " + version + " is starting");

            string[] autoloadPlugs = this.configHandler.AutoloadPlugins;
            foreach (string plugName in autoloadPlugs)
            {
                nativeExecution.AutoLoadCommand(plugName);
            }

            // send js code to fire ready event
            string nativeReady = "(function(){ cordova.require('cordova/channel').onNativeReady.fire()})();";
            try
            {
                CordovaBrowser.InvokeScript("eval", 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?");
            }
            // attach js code to dispatch exitApp 
            string appExitHandler = "(function(){navigator.app = navigator.app || {}; navigator.app.exitApp= function(){cordova.exec(null,null,'CoreEvents','__exitApp',[]); }})();";
            try
            {
                CordovaBrowser.InvokeScript("eval", new string[] { appExitHandler });
            }
            catch (Exception /*ex*/)
            {
                Debug.WriteLine("Error calling js to add appExit funtion.");
            }

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


        void CordovaBrowser_Navigating(object sender, NavigatingEventArgs e)
        {
            if (!configHandler.URLIsAllowed(e.Uri.ToString()))
            {
                Debug.WriteLine("Whitelist exception: Stopping browser from navigating to :: " + e.Uri.ToString());
                e.Cancel = true;
                return;
            }

            this.PageDidChange = true;
            this.nativeExecution.ResetAllCommands();
        }

        /*
         *  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 CordovaBrowser_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;
                    case "__exitapp":
                        Debug.WriteLine("Received exitApp command from javascript, app will now exit.");
                        CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('pause');" });
                        CordovaBrowser.InvokeScript("eval", new string[] { "setTimeout(function(){ cordova.fireDocumentEvent('exit'); cordova.exec(null,null,'CoreEvents','__finalexit',[]); },0);" });
                        break;
                    case "__finalexit":
                        IsExiting = true;
                        // hide the browser to prevent white flashes, since about:blank seems to always be white
                        CordovaBrowser.Opacity = 0d; 
                        CordovaBrowser.Navigate(new Uri("about:blank", UriKind.Absolute));
                        break;
                }
            }
            else
            {
                if (configHandler.IsPluginAllowed(commandCallParams.Service))
                {
                    commandCallParams.Namespace = configHandler.GetNamespaceForCommand(commandCallParams.Service);
                    nativeExecution.ProcessCommand(commandCallParams);
                }
                else
                {
                    Debug.WriteLine("Error::Plugin not allowed in config.xml. " + commandCallParams.Service);
                }
            }
        }

        public void LoadPage(string url)
        {
            if (this.configHandler.URLIsAllowed(url))
            {
                this.CordovaBrowser.Navigate(new Uri(url, UriKind.RelativeOrAbsolute));
            }
            else
            {
                Debug.WriteLine("Oops, Can't load url based on config.xml :: " + url);
            }
        }

        private void CordovaBrowser_Unloaded(object sender, RoutedEventArgs e)
        {
            IBrowserDecorator console;
            if (browserDecorators.TryGetValue("ConsoleLog", out console))
            {
                ((ConsoleHelper)console).DetachHandler();
            }

            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);
        }

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

        private void CordovaBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
           foreach(IBrowserDecorator iBD in browserDecorators.Values)
           {
               iBD.InjectScript();
           }
        }

        /// <summary>
        /// Converts hex color string to a new System.Windows.Media.Color structure.
        /// If the hex is only rgb, it will be full opacity.
        /// </summary>
        protected Color ColorFromHex(string hexString)
        {
            string cleanHex = hexString.Replace("#", "").Replace("0x", "");
            // turn #FFF into #FFFFFF
            if (cleanHex.Length == 3)
            {
                cleanHex = "" + cleanHex[0] + cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2];
            }
            // add an alpha 100% if it is missing
            if (cleanHex.Length == 6)
            {
                cleanHex = "FF" + cleanHex;
            }
            int argb = Int32.Parse(cleanHex, NumberStyles.HexNumber);
            Color clr = Color.FromArgb((byte)((argb & 0xff000000) >> 0x18),
                              (byte)((argb & 0xff0000) >> 0x10),
                              (byte)((argb & 0xff00) >> 8),
                              (byte)(argb & 0xff));
            return clr;
        }
    }
}
