module Serve
open System
open System.Drawing
open System.IO
open System.Net
open System.Threading
open Execute
open Load
let private main_page link prog steps =
 sprintf
  "
   
   
     
     Krunimír
     
   
   
     
   
   
  " link prog steps
let private handle (context:HttpListenerContext) =
  let request = context.Request
  let response = context.Response
  let send_bytes content (buffer:byte array) =
    response.ContentType <- content
    response.ContentLength64 <- int64 buffer.Length
    let output = response.OutputStream
    output.Write(buffer, 0, buffer.Length)
    output.Close()
  let send_string content (str:string) =
    let buffer = System.Text.Encoding.UTF8.GetBytes(str)
    send_bytes content buffer
  match request.Url.AbsolutePath with
  | "/" ->
      let args = request.QueryString
      let prog = match args.["prog"] with null -> "" | str  -> str
      let mutable steps = try Int32.Parse args.["steps"] with _ -> 0
      let mutable link = ""
      if args.["prev"] <> null && steps > 0 then steps <- steps - 1
      if args.["next"] <> null then steps <- steps + 1
      if args.["prev"] <> null || args.["next"] <> null || args.["go"] <> null then
        link <- sprintf " "
                        (Uri.EscapeDataString prog) steps
      send_string "text/html" <| main_page link prog steps
  | "/simulate" ->
      let args = request.QueryString
      let prog = args.["prog"]
      let steps = Int32.Parse args.["steps"]
      let image =
        try
          let memstream = new MemoryStream()
          draw (load prog) steps memstream
          memstream.ToArray()
        with e ->
          use bitmap = new Bitmap(700, 700, Imaging.PixelFormat.Format24bppRgb)
          use graphics = Graphics.FromImage(bitmap)
          graphics.Clear(Color.White)
          graphics.DrawString("There was an error: " + e.Message,
                              SystemFonts.DefaultFont, Brushes.Red,
                              new RectangleF(0.f, 0.f, 700.f, 700.f))
          let memstream = new MemoryStream()
          bitmap.Save(memstream, Imaging.ImageFormat.Png)
          memstream.ToArray()
      send_bytes "image/png" image
  | _ ->
      response.StatusCode <- 404
      send_string "text/html" <| "
"
                        (Uri.EscapeDataString prog) steps
      send_string "text/html" <| main_page link prog steps
  | "/simulate" ->
      let args = request.QueryString
      let prog = args.["prog"]
      let steps = Int32.Parse args.["steps"]
      let image =
        try
          let memstream = new MemoryStream()
          draw (load prog) steps memstream
          memstream.ToArray()
        with e ->
          use bitmap = new Bitmap(700, 700, Imaging.PixelFormat.Format24bppRgb)
          use graphics = Graphics.FromImage(bitmap)
          graphics.Clear(Color.White)
          graphics.DrawString("There was an error: " + e.Message,
                              SystemFonts.DefaultFont, Brushes.Red,
                              new RectangleF(0.f, 0.f, 700.f, 700.f))
          let memstream = new MemoryStream()
          bitmap.Save(memstream, Imaging.ImageFormat.Png)
          memstream.ToArray()
      send_bytes "image/png" image
  | _ ->
      response.StatusCode <- 404
      send_string "text/html" <| "Error 404
Cannot find requested url " + request.Url.ToString()
let serve port =
  use server = new HttpListener()
  server.Prefixes.Add(sprintf "http://localhost:%d/" port)
  server.Prefixes.Add(sprintf "http://127.0.0.1:%d/" port)
  for ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList do
   server.Prefixes.Add(sprintf "http://%A:%d/" ip port)
  server.Start()
  while true do
    let context = server.GetContext()
    if not (ThreadPool.QueueUserWorkItem(fun _ -> handle context)) then
      failwith "Cannot start thread to handle the Http request"