var assert = require("assert")

console.log("1..4")

function test_local(swf) {
  var stdin_word = "hello"
  var env_foo = "bar"
  var argv_1 = "123"

  with_timeout(
    function (callback) {
      require("child_process").exec([
        "echo", stdin_word, "|",
        "foo=" + env_foo,
        "bin/run-stdio-swf", swf,
        argv_1
      ].join(" "), callback)
    }, function (error, stdout, stderr) {
      test(swf, function () {
        assert.equal(stdout, stdin_word + "\n")
        assert.equal(stderr, env_foo + "\n")
        assert.equal(error.code, parseInt(argv_1))
      })
    }, function () {
      test(swf, function () {
        assert.fail("timeout")
      })
    }
  )
}

function test_web(swf, port) {
  var flashplayer
  var expected_path = "/123"

  with_timeout(
    function (callback) {
      require("http").createServer(function (request, response) {
        if (request.url === "/crossdomain.xml") {
          response.writeHead(200, { "content-type": "text/xml" })
          response.end('\
<cross-domain-policy>\n\
  <site-control permitted-cross-domain-policies="master-only"/>\n\
  <allow-access-from domain="*" to-ports="*"/>\n\
</cross-domain-policy>\n\
')
         } else {
           flashplayer.kill()
           this.close()
           callback(request.url)
         }
      }).listen(port, function () {
        flashplayer = start_flashplayer(swf, {
          port: port,
          path: expected_path
        })
      })
    }, function (actual_path) {
      test(swf, function () {
        assert.equal(actual_path, expected_path)
      })
    }, function () {
      test(swf, function () {
        assert.fail("timeout")
      })
    }
  )
}

function start_flashplayer(swf, parameters) {
  var executable = "/Applications/Flash Player Debugger.app/" +
    "Contents/MacOS/Flash Player Debugger"

  return require("child_process").spawn(executable, [
    swf + "?" + stringify_query_parameters(parameters || {})
  ])
}

function stringify_query_parameters(parameters) {
  return Object.keys(parameters || {}).map(function (name) {
    return encodeURIComponent(name) + "=" +
      encodeURIComponent(parameters[name])
  }).join("&")
}

function with_timeout(body, callback, errback) {
  var timeout = setTimeout(function () {
    errback()
    callback = null
  }, 5000)

  body(function () {
    clearTimeout(timeout)

    if (callback) {
      callback.apply(null, arguments)
    }
  })
}

//----------------------------------------------------------

function test(name, callback) {
  try {
    callback()
    test_passed(name)
  } catch (error) {
    test_failed(name)
    throw error
  }
}

function test_passed(name) {
  console.log("ok - " + name)
}

function test_failed(name) {
  console.log("not ok - " + name)
}

//----------------------------------------------------------

test_web("test_web_flash.swf", 56788)
test_web("test_web_flex.swf", 56789)

test_local("test_local_flash.swf")
test_local("test_local_flex.swf")

@@ -29,29 +29,8 @@
 %22)%0A%0A
-console.log(%221..4%22)%0A%0A
 func
@@ -600,66 +600,30 @@
 test
-(swf, function () %7B%0A        assert.fail(%22timeout%22)%0A      %7D
+_failed(swf, %22timeout%22
 )%0A  
@@ -669,16 +669,24 @@
  %7B%0A  var
+ server,
  flashpl
@@ -716,24 +716,160 @@
 h = %22/123%22%0A%0A
+  function cleanup() %7B%0A    server && server.close()%0A    flashplayer && flashplayer.kill(%22SIGKILL%22)%0A    server = flashplayer = null%0A  %7D%0A%0A
   with_timeo
@@ -895,32 +895,41 @@
 allback) %7B%0A     
+ server =
  require(%22http%22)
@@ -1308,62 +1308,8 @@
 e %7B%0A
-           flashplayer.kill()%0A           this.close()%0A
     
@@ -1356,16 +1356,30 @@
       %7D)
+%0A%0A      server
 .listen(
@@ -1545,24 +1545,40 @@
 ual_path) %7B%0A
+      cleanup()%0A
       test(s
@@ -1684,70 +1684,50 @@
     
-test(swf, function () %7B%0A        assert.fail(%22timeout%22)%0A      %7D
+cleanup()%0A      test_failed(swf, %22timeout%22
 )%0A  
@@ -2669,25 +2669,27 @@
 name
-)%0A    throw error
+, error.toString())
 %0A  %7D
@@ -2775,24 +2775,35 @@
 _failed(name
+, diagnosis
 ) %7B%0A  consol
@@ -2828,16 +2828,61 @@
 + name)%0A
+  console.log(diagnosis.replace(/%5E/g, %22# %22))%0A
 %7D%0A%0A//---

Refactor tests.