using System;
using System.IO;
using System.Net;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Net;
using Microsoft.SPOT.Net.NetworkInformation;

using GHI.Premium.Net;

namespace FTP
{
    public class NoWiFiAdapterException : System.Exception
    {
        public NoWiFiAdapterException() : base() { }
        public NoWiFiAdapterException(string message) : base(message) { }
        public NoWiFiAdapterException(string message, System.Exception inner) : base(message, inner) { }
    }

    public class WifiManager
    {
        public  enum            InfrastructureType { AP, AD_HOC };
        public  enum            ConnectionType     { STATIC, DHCP };

        private WiFiRS9110      _wifi;
        private bool            _useDebug;
        private string          _wifi_SSID;
        private string          _wifi_Password;
    
        public WifiManager()
        {
            _useDebug = true;
            _wifi_SSID = "MBARI WiFi";
            _wifi_Password = "";

            WiFiAvailable();
        }

        public void Enable(InfrastructureType infrastructure, ConnectionType connection) 
        {
            if (_useDebug)
                Debug.Print("Enable WiFi Adapter");

            // Parameters are SPI Bus, Chip Select, External Interrupt and Reset signal)
            _wifi = new WiFiRS9110(SPI.SPI_module.SPI2, (Cpu.Pin)10, (Cpu.Pin)18, (Cpu.Pin)20);// FEZ Spider Socket 6

            if (infrastructure == InfrastructureType.AP) 
            {
                if (!_wifi.IsOpen)
                    _wifi.Open();

                _wifi.NetworkAddressChanged += new NetworkInterfaceExtension.NetworkAddressChangedEventHandler(wifi_NetworkAddressChanged);
                _wifi.WirelessConnectivityChanged += new WiFiRS9110.WirelessConnectivityChangedEventHandler(wifi_WirelessConnectivityChanged);
                NetworkInterfaceExtension.AssignNetworkingStackTo(_wifi);

                if (connection == ConnectionType.DHCP)
                {
                    if (!_wifi.NetworkInterface.IsDhcpEnabled)
                        _wifi.NetworkInterface.EnableDhcp();
                }
                else
                {
                    _wifi.NetworkInterface.EnableStaticIP("134.89.8.58", "255.255.254.0", "134.89.8.1");
                }
            }
            else
            {
                _wifi.StartAdHocHost("CPF-AD-HOC", SecurityMode.Open, "", 10);
            }

            JoinNetwork();
        }

        private void WiFiAvailable()
        {
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
           
            foreach(NetworkInterface iface in interfaces) 
            {
                if (iface.NetworkInterfaceType == Microsoft.SPOT.Net.NetworkInformation.NetworkInterfaceType.Wireless80211)
                {
                    Debug.Print("Found a wireless interface");
                    return;
                }
            }
            Debug.Print("No wireless interface available");
            throw new NoWiFiAdapterException();
        }

        // Your router SSID and PassKey neede to be set in here
        private void JoinNetwork()
        {
            try
            {
                // Your router SSID needed here
                WiFiNetworkInfo[] ScanResp = _wifi.Scan(_wifi_SSID); 
                if (ScanResp != null && ScanResp.Length > 0)
                {
                    _wifi.Join(ScanResp[0], _wifi_Password); 
                    if (_useDebug)
                    { Debug.Print(_wifi_SSID.ToString()); }
                }
                else
                {
                    if (_useDebug)
                    { Debug.Print("*** " + _wifi_SSID.ToString() +  " was not found"); }
                }
            }
            catch (Exception e)
            {
                if (_useDebug)
                { Debug.Print("!!! Exception : " + e.Message); }
            }
        }

        public string SSID
        {
            get { return _wifi_SSID; }
            set { _wifi_SSID = value;  }
        }

        public string Password
        {
            get { return _wifi_Password; }
            set { _wifi_Password = value; }
        }

        private void wifi_NetworkAddressChanged(object sender, EventArgs e)
        {
            if (_useDebug)
                Debug.Print("***Network Address Changed , IP Address : " + _wifi.NetworkInterface.IPAddress);
        }

        private void wifi_WirelessConnectivityChanged(object sender, WiFiRS9110.WirelessConnectivityEventArgs e)
        {
            if (_useDebug)
            {
                Debug.Print("***Wireless Connectivity Changed");
                if (e != null)
                    Debug.Print("***RSSI : " + e.NetworkInformation.RSSI.ToString());
                Debug.Print("***IP Address : " + _wifi.NetworkInterface.IPAddress);
            }
            AvailabilityChanged(e.IsConnected);
        }

        public bool Connected
        {
            get { return _wifi.IsLinkConnected; }
        }

        public string GatewayAddress
        {
            get
            {
                try
                {
                    return _wifi.NetworkInterface.GatewayAddress;
                }
                catch (Exception)
                {
                    return "0.0.0.0";
                }
            }
        }

        public string IPAddress
        {
            get
            {
                try
                {
                    return _wifi.NetworkInterface.IPAddress;
                }
                catch (Exception)
                {
                    return "127.0.0.1";
                }
            }
        }

        public string SubnetMask
        {
            get
            {
                try
                {
                    return _wifi.NetworkInterface.SubnetMask;
                }
                catch (Exception)
                {
                    return "255.255.255.0";
                }
            }
        }

        private void NetworkChange_NetworkAvailabilityChanged(object sender, WiFiRS9110.WirelessConnectivityEventArgs e)
        {
            AvailabilityChanged(e.IsConnected);
        }

        private void AvailabilityChanged(bool IsConnected)
        {
            if (IsConnected)
            {
                if (_useDebug)
                    Debug.Print("Connected to MBARI WiFi");
            }
            else
            {
                if (_useDebug)
                    Debug.Print("Disconnected from MBARI WiFi");
            }
        }

    }
}

/*
using System;
using System.Threading;
using System.Net;
using System.Text;
using System.Net.Sockets;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware; //need for Utility class
using GHI.Premium.Net;

namespace WIFI
{
    public partial class Program
    {
        //Your choice...
        private static WiFiRS9110 wifi;
        private static bool useDebug = true;

        public static void Main()
        {
            wifi = new WiFiRS9110(SPI.SPI_module.SPI2, (Cpu.Pin)10, (Cpu.Pin)18, (Cpu.Pin)20);// FEZ Spider Socket 6

            if (!wifi.IsOpen)
                wifi.Open();

            wifi.NetworkInterface.EnableStaticIP("134.89.8.58", "255.255.254.0", "134.89.8.1");

            wifi.NetworkAddressChanged += new NetworkInterfaceExtension.NetworkAddressChangedEventHandler(wifi_NetworkAddressChanged);
            wifi.WirelessConnectivityChanged += new WiFiRS9110.WirelessConnectivityChangedEventHandler(wifi_WirelessConnectivityChanged);

            NetworkInterfaceExtension.AssignNetworkingStackTo(wifi);
            JoinNetwork();
        }

        // Your router SSID and PassKey neede to be set in here
        static void JoinNetwork()
        {
            try
            {
                // Your router SSID needed here
                WiFiNetworkInfo[] ScanResp = wifi.Scan("MBARI WiFi"); //< Needs to be changed to SSID you are looking for
                if (ScanResp != null && ScanResp.Length > 0)
                {
                    //Your passkey needed here
                    wifi.Join(ScanResp[0], ""); //< needs to be changed to your Key
                    if (useDebug) { Debug.Print("***Joined to MBARI WiFi..."); }
                }
                else
                {
                    if (useDebug) { Debug.Print("***MBARI WiFi was not found"); }
                }
            }
            catch (Exception e)
            {
                if (useDebug) { Debug.Print("!!! Exception : " + e.Message); }
            }
        }

        static void wifi_NetworkAddressChanged(object sender, EventArgs e)
        {
            Debug.Print("***Network Address Changed , IP Address : " + wifi.NetworkInterface.IPAddress);
            // NTPTime("time.windows.com", (-(60 * 7)));
            // if (useDebug) { Debug.Print("### Time Server : " + DateTime.Now.ToString()); }
            RunServer();
        }

        static void wifi_WirelessConnectivityChanged(object sender, WiFiRS9110.WirelessConnectivityEventArgs e)
        {
            if (useDebug)
            {
                Debug.Print("***Wireless Connectivity Changed");
                Debug.Print("***RSSI : " + e.NetworkInformation.RSSI.ToString());
                Debug.Print("***IP Address : " + wifi.NetworkInterface.IPAddress);
            }

            if (e.IsConnected)
            {
                // Add the time zone offset to the retrieved UTC Time
                // (in this example, it assumes that the time zone is GMT-6).
                // You will need to adjust TimeService.SetTimeZoneOffset value for your time zone

                //UTC -6 hours for Central Standard Time. Use -(60 * 5) for Daylight savings time.
                //You will need to change NTPTime to your Time Zone
            }
        }
*/
