/*  
	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.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Net.NetworkInformation;

namespace WPCordovaClassLib.Cordova.Commands
{

    // http://msdn.microsoft.com/en-us/library/microsoft.phone.net.networkinformation(v=VS.92).aspx
    // http://msdn.microsoft.com/en-us/library/microsoft.phone.net.networkinformation.devicenetworkinformation(v=VS.92).aspx

    public class NetworkStatus : BaseCommand
    {
        const string UNKNOWN = "unknown";
        const string ETHERNET = "ethernet";
        const string WIFI = "wifi";
        const string CELL_2G = "2g";
        const string CELL_3G = "3g";
        const string CELL_4G = "4g";
        const string NONE = "none";
        const string CELL = "cellular";

        private bool HasCallback = false;

        public NetworkStatus()
        {
            DeviceNetworkInformation.NetworkAvailabilityChanged += new EventHandler<NetworkNotificationEventArgs>(ChangeDetected);
        }

        public override void OnResume(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
        {
            this.getConnectionInfo("");
        }

        public void getConnectionInfo(string empty)
        {
            HasCallback = true;
            updateConnectionType(checkConnectionType());
        }

        private string checkConnectionType()
        {
            if (DeviceNetworkInformation.IsNetworkAvailable)
            {
                if (DeviceNetworkInformation.IsWiFiEnabled)
                {
                    return WIFI;
                }
                else
                {
                    return DeviceNetworkInformation.IsCellularDataEnabled ? CELL : UNKNOWN;
                }
            }
            return NONE;
        }

        private string checkConnectionType(NetworkInterfaceSubType type)
        {
            switch (type)
            {
                case NetworkInterfaceSubType.Cellular_1XRTT: //cell
                case NetworkInterfaceSubType.Cellular_GPRS: //cell
                    return CELL;
                case NetworkInterfaceSubType.Cellular_EDGE: //2
                    return CELL_2G;
                case NetworkInterfaceSubType.Cellular_3G:
                case NetworkInterfaceSubType.Cellular_EVDO: //3
                case NetworkInterfaceSubType.Cellular_EVDV: //3 
                case NetworkInterfaceSubType.Cellular_HSPA: //3
                    return CELL_3G;
                case NetworkInterfaceSubType.WiFi:
                    return WIFI;
                case NetworkInterfaceSubType.Unknown:
                case NetworkInterfaceSubType.Desktop_PassThru:
                default:
                    return UNKNOWN;
            }
        }

        void ChangeDetected(object sender, NetworkNotificationEventArgs e)
        {
            switch (e.NotificationType)
            {
                case NetworkNotificationType.InterfaceConnected:
                    updateConnectionType(checkConnectionType(e.NetworkInterface.InterfaceSubtype));
                    break;
                case NetworkNotificationType.InterfaceDisconnected:
                    updateConnectionType(NONE);
                    break;
                default:
                    break;
            }
        }

        private void updateConnectionType(string type)
        {
            // This should also implicitly fire offline/online events as that is handled on the JS side
            if (this.HasCallback)
            {
                PluginResult result = new PluginResult(PluginResult.Status.OK, type);
                result.KeepCallback = true;
                DispatchCommandResult(result);
            }
        }
    }
}
