//    Copyright (C) 2016  Jonathan Jason Dennis [Meticulus]
//    theonejohnnyd@gmail.com
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as
//    published by the Free Software Foundation, either version 3 of the 
//    License, or (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
﻿using System;
using System.Collections.Generic;
using System.Text;
using meticulus.servers.common.plugin;
using meticulus.settings;
using meticulus.servers.web;
using System.Net.Sockets;
using System.IO;
using meticulus.reflection;
using meticulus.servers.common;
using meticulus.global;

namespace meticulus.servers.proxy.plugin
{
    public class switcharoo:iserver_plugin
    {
        List<Setting>				 	_settings = new List<Setting>();
        List<filter_file>				_switchPairs = new List<filter_file>() ;
        Boolean 						_active = true;

		private static String _tag;

        public switcharoo()
        {
			_tag = GetType ().Name;
             Setting enable = new Setting(
				typeof(Boolean),"Enable",
				true,
				"Enable/Disable Switcharoo. Switcharoo allows you to specify a file to be used as the response when the condition is satified!",
			    "General");
             enable.OnSettingChanged += new EventHandler(enable_OnSettingChanged);

            Setting switchPairsList = new Setting(
				typeof(filter_file[]),
				"Switch Pairs",
				new filter_file[0],
			"A list of filters with an associated file.",
			"Switch Pairs List");
            switchPairsList.OnSettingChanged += new EventHandler(switchPairsList_OnSettingChanged);
            _settings.AddRange(new Setting[]{switchPairsList, enable});
        }

        void enable_OnSettingChanged(object sender, EventArgs e)
        {
            _active = (Boolean)((Setting)sender).Value;
            if(OnActiveChanged!=null){OnActiveChanged(this,new EventArgs());}
        }

        void switchPairsList_OnSettingChanged(object sender, EventArgs e)
        {
            filter_file[] commaPairs = (filter_file[])((Setting)sender).Value;
			if(commaPairs == null)
				return;
            _switchPairs.Clear();
            lock (_switchPairs)
            {
                foreach (filter_file switchPair in commaPairs)
                {
                    _switchPairs.Add(switchPair);

                }
            }
        }

        #region IServerPlugin Members

        public bool Active
        {
            get { return _active; }
        }

        public string Title
        {
            get { return "Switcharoo"; }
        }

        public bool Process(object context, Object tag)
        {
            proxy_transaction pt = (proxy_transaction)context;
            Boolean retval = false;
			log.i (_tag, String.Format ("Processing {0}", pt.Request.Uri.ToString()));
            lock (_switchPairs)
            {
                foreach (filter_file ff in _switchPairs)
                {
					if (ConditionChecker.Check (pt, ff.ConditionString)) {
						log.i (_tag, String.Format ("Condition {0} true for {1}", ff.Name, pt.Request.Uri.ToString ()));
						if (File.Exists (ff.target)) {
							log.i (_tag, String.Format ("File {0} exists", ff.target));
							//http_response tempres = Proxiedhttp_response.Create(pt.Request, pt.ServerConnection.Client, pt.ServerStream);
							pt.Response = new http_response ();
							//realres.Initialize(pt.ServerConnection.Client, pt.ServerStream);
							pt.Response.Body = new MemoryStream (File.ReadAllBytes (ff.target));
							//realres.Header.Values.Remove("Content-Encoding");
							pt.Response.Header.SetValue ("Content-Length", pt.Response.Body.Length.ToString ());
							pt.Response.Header.SetValue ("Host", pt.Request.Uri.Host);
							pt.Response.Header.SetValue ("Content-Type", mime_types.GetMimeType (Path.GetExtension (ff.target)));
							pt.Response.Header.Statuscode = "200";
							pt.Response.Header.Statusmessage = "OK";
							pt.Response.End = (int)pt.Response.Body.Length;
							pt.Response.Respond (pt.ClientConnection.Client, pt.ClientStream);
							log.i (_tag, String.Format ("Sent {0} to client", ff.target));
							retval = true;
							break;
						} else {
							log.e (_tag, String.Format ("File {0} not found?", ff.target));
						}
					} else {
						log.i (_tag, String.Format ("{0} does not match condition {1}", pt.Request.Uri.ToString (), ff.Name));
					}
                }
            }
            return retval;
        }

        public event EventHandler OnActiveChanged;

        public object Tag
        {
            get { return "proxy-request"; }
        }

        #endregion

        #region ISettings Members

        public SettingCollection Settings
        {
            get { return new SettingCollection(this.Title,_settings.ToArray());}
        }

        #endregion
    }
}
