// Overling test suite - tests actor hierarchy management

var time = use('time');

// Track test results
var testResults = {
  type: 'test_results',
  test_name: 'overling',
  passed: 0,
  failed: 0,
  total: 0,
  failures: [],
  duration: 0
};

var startTime;

// Helper to run a single test
function runTest(testName, testFn) {
  var passed = true;
  var messages = [];
  
  try {
    testFn(function(result) {
      passed = result.passed;
      messages = result.messages || [];
      
      // Update results
      testResults.total++;
      if (passed) {
        testResults.passed++;
      } else {
        testResults.failed++;
        testResults.failures.push({
          name: testName,
          error: messages.join('\n')
        });
      }
      
      // Log individual result
      log.console(testName + ' - ' + (passed ? 'Passed' : 'Failed'));
      if (!passed && messages.length > 0) {
        log.console('  ' + messages.join('\n  '));
      }
    });
  } catch (e) {
    testResults.total++;
    testResults.failed++;
    testResults.failures.push({
      name: testName,
      error: 'Exception thrown: ' + (e.stack || e.toString())
    });
    log.console(testName + ' - Failed');
    log.console('  Exception thrown: ' + (e.stack || e.toString()));
  }
}

// Test suite
var tests = [
  {
    name: "Actor should be able to spawn underlings",
    run: function(done) {
      var underlingCount = 0;
      var targetCount = 3;
      
      // Spawn several underlings
      for (var i = 0; i < targetCount; i++) {
        $_.start(function(greet) {
          underlingCount++;
          if (underlingCount == targetCount) {
            done({
              passed: true,
              messages: []
            });
          }
        }, "underling", ["test" + i]);
      }
      
      // Timeout protection
      $_.delay(function() {
        if (underlingCount < targetCount) {
          done({
            passed: false,
            messages: ["Only spawned " + underlingCount + " of " + targetCount + " underlings"]
          });
        }
      }, 1);
    }
  },
  
  {
    name: "Actor should be able to stop underlings",
    run: function(done) {
      var stopped = false;
      
      $_.start(function(greet) {
        // Stop the underling immediately
        $_.stop(greet.actor);
        stopped = true;
        
        // Give it a moment to ensure stop worked
        $_.delay(function() {
          done({
            passed: stopped,
            messages: stopped ? [] : ["Failed to stop underling"]
          });
        }, 0.1);
      }, "underling", ["stop_test"]);
    }
  },
  
  {
    name: "Actor unneeded function should terminate after timeout",
    run: function(done) {
      var finished = false;
      
      $_.unneeded(function() {
        finished = true;
        done({
          passed: true,
          messages: []
        });
      }, 0.5); // 500ms timeout
      
      // Check that it hasn't finished too early
      $_.delay(function() {
        if (finished) {
          done({
            passed: false,
            messages: ["unneeded finished too early"]
          });
        }
      }, 0.2);
    }
  }
];

// Message receiver
$_.receiver(function(msg) {
  if (msg.type == 'run_tests') {
    startTime = time.number();
    var testsCompleted = 0;
    
    // Run all tests
    for (var i = 0; i < tests.length; i++) {
      var test = tests[i];
      runTest(test.name, test.run);
    }
    
    // Wait for all async tests to complete
    var checkComplete = function() {
      if (testResults.total >= tests.length) {
        // Calculate duration
        testResults.duration = time.number() - startTime;
        
        // Send results back
        send(msg, testResults);
      } else {
        $_.delay(checkComplete, 0.1);
      }
    };
    
    $_.delay(checkComplete, 0.1);
  }
});