using System;
using System.Collections.Generic;
using System.Text;
using Org.Mentalis.Proxy;
using Org.Mentalis.Proxy.Socks;
using System.Net;
using System.Collections;

namespace ShopBot.SocksServer
{
    public struct ListenEntry
    {
        /// <summary>
        /// The Listener object.
        /// </summary>
        public Listener listener;
        /// <summary>
        /// The Listener's ID. It must be unique troughout the Listeners collection.
        /// </summary>
        public Guid guid;
        /// <summary>
        /// Determines whether the specified Object is equal to the current Object.
        /// </summary>
        /// <param name="obj">The Object to compare with the current Object.</param>
        /// <returns>True if the specified Object is equal to the current Object; otherwise, false.</returns>
        public override bool Equals(object obj)
        {
            return ((ListenEntry)obj).guid.Equals(guid);
        }
    }
    class ProxyServer
    {
        int _SocksPort;
        int _HttpPort;

        public ProxyServer(int Socks5Port, int HttpPort)
        {
            _SocksPort = Socks5Port;
            _HttpPort = HttpPort;
        }

        public void Start()
        {
            Listener SocksListener = CreateListener("Org.Mentalis.Proxy.Socks.SocksListener", "host:127.0.0.1;int:" + _SocksPort);
            SocksListener.Start();
            AddListener(SocksListener);

            Listener HttpListener = CreateListener("Org.Mentalis.Proxy.Http.HttpListener", "host:127.0.0.1;int:" + _HttpPort);
            HttpListener.Start();
            AddListener(HttpListener);
        }

        public void AddListener(Listener newItem)
        {
            if (newItem == null)
                throw new ArgumentNullException();
            ListenEntry le = new ListenEntry();
            le.listener = newItem;
            le.guid = Guid.NewGuid();
            while (Listeners.Contains(le))
            {
                le.guid = Guid.NewGuid();
            }
            Listeners.Add(le);
            Console.WriteLine(newItem.ToString() + " started.");
        }

        public Listener CreateListener(string type, string cpars)
        {
            try
            {
                string[] parts = cpars.Split(';');
                object[] pars = new object[parts.Length];
                string oval = null, otype = null;
                int ret;
                // Start instantiating the objects to give to the constructor
                for (int i = 0; i < parts.Length; i++)
                {
                    ret = parts[i].IndexOf(':');
                    if (ret >= 0)
                    {
                        otype = parts[i].Substring(0, ret);
                        oval = parts[i].Substring(ret + 1);
                    }
                    else
                    {
                        otype = parts[i];
                    }
                    switch (otype.ToLower())
                    {
                        case "int":
                            pars[i] = int.Parse(oval);
                            break;
                        case "host":
                            pars[i] = Dns.Resolve(oval).AddressList[0];
                            break;
                        case "null":
                            pars[i] = null;
                            break;
                        case "string":
                            pars[i] = oval;
                            break;
                        case "ip":
                            pars[i] = IPAddress.Parse(oval);
                            break;
                        default:
                            pars[i] = null;
                            break;
                    }
                }
                return (Listener)Activator.CreateInstance(Type.GetType(type), pars);
            }
            catch
            {
                return null;
            }
        }
        protected ArrayList Listeners
        {
            get
            {
                return m_Listeners;
            }
        }
        private ArrayList m_Listeners = new ArrayList();
    }
}
