/* 

   Copyright (C) Arnaud Houdelette		2012-2014
   Copyright (C) Emmanuel Langlois		2012-2014

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License.
   
   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 General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Web;
using System.Net;
using System.Threading;
using System.Collections.Generic;

namespace DMX2
{
	public class WebServer : IDisposable
	{
		HttpListener listner;

		Thread loopthread=null;

		string page;
		List<string> resources;

		public WebServer ()
		{
			using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("page.html"))
				using (System.IO.TextReader reader = new System.IO.StreamReader(stream))
						page = reader.ReadToEnd();

			resources = new List<string>(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames());

			loopthread = new Thread(new ThreadStart(MainLoop));
			loopthread.Start();
		}

		void MainLoop ()
		{
			listner = new HttpListener ();
			listner.Prefixes.Add ("http://*:8089/");
			listner.Start ();
			HttpListenerContext context;

			try {
				while (null!=(context = listner.GetContext())) {

					Console.WriteLine (context.Request.RawUrl);

					string responseString = GetResponse (context);
						// Pour les resources, on les renvoie si elles existent
					if (context.Request.Url.LocalPath.StartsWith ("/res/")) {
						string res = context.Request.Url.LocalPath.Remove(0,5).Replace('/','.');
						if(resources.Contains(res))
							using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(res))
							
						{
							byte[] buff = new byte[1024]; int l;
							while( (l=stream.Read(buff,0,buff.Length))>0){
								context.Response.OutputStream.Write(buff,0,l);
							}
						}
						
					}
					else
					{

						byte[] buffer = System.Text.Encoding.UTF8.GetBytes (responseString); 
						context.Response.ContentLength64 = buffer.Length;
						context.Response.OutputStream.Write (buffer, 0, buffer.Length);

					}
					context.Response.OutputStream.Close ();
				}
			} catch {
			}

		}	

		string GetResponse (HttpListenerContext ctx)
		{
			HttpListenerRequest req = ctx.Request;
			// Pas de conduite chargée, on renvoi un simple message
			if (Conduite.Courante == null) return "<html><body>Pas de conduite</body></html>";

		
			int circuit, univ, dimmer, val;

			// En fonction du http://xxxxxx:yyyy/?id=
			switch (req.QueryString["id"]) {
			default: // Par défaut, on renvoie la page 

				string univlist = ""; int i = 0;
				foreach (UniversDMX univers in Conduite.Courante.Patches)
					univlist = univlist + string.Format("<option value=\"{0}\">{1}</option>",i++,univers.Nom);
				string data = page.Replace("<UNIVLIST>",univlist);
				return data;

			case "2" : 
				// id=2 > controle d'un dimmer
				if(!int.TryParse(req.QueryString["univ"],out univ)) return "NOK";
				if(!int.TryParse(req.QueryString["dimmer"],out dimmer)) return "NOK";
				if(!int.TryParse(req.QueryString["val"],out val)) return "NOK";
				if(univ<0 || univ>= Conduite.Courante.Patches.Count) return "NOK";
				if(dimmer<=0 || dimmer > 512) return "NOK";
				if(val <0 || val > 255) return "NOK";
				Conduite.Courante.Patches[univ].AllumageForce = dimmer-1;
				Conduite.Courante.Patches[univ].AllumageForceVal = val;
				return "OK";

			case "3":

				// id=3 > controle d'un circuit
				if(!int.TryParse(req.QueryString["circuit"],out circuit)) return "NOK";
				if(!int.TryParse(req.QueryString["val"],out val)) return "NOK";
				if(circuit<=0 || circuit> Conduite.Courante.Circuits.Count) return "NOK";
				if(val <0 || val > 255) return "NOK";
				Conduite.Courante.CircuitTelecomande = Conduite.Courante.Circuits[circuit-1];
				Conduite.Courante.CircuitTelecomandeVal = val;
				return "OK";
			}
		}

	

		#region IDisposable implementation
		public void Dispose ()
		{
			listner.Close();
			loopthread.Abort();
			loopthread.Join();
		}
		#endregion


	}
}

