// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library vmservice_test_helper;

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:expect/expect.dart';

abstract class ServiceWebSocketRequestHelper {
  final String url;
  final Completer _completer = new Completer();
  WebSocket _socket;

  ServiceWebSocketRequestHelper(this.url);

  // Returns [this] when connected.
  Future connect() {
    return WebSocket.connect(url).then((ws) {
      _socket = ws;
      _socket.listen((message) {
        var map = JSON.decode(message);
        var response = JSON.decode(map['response']);
        onResponse(map['seq'], response);
      });
      return this;
    });
  }

  void complete() {
    _completer.complete(this);
  }

  Future get completed => _completer.future;

  // Must call complete.
  void onResponse(var seq, Map response);
  void runTest();

  Future sendMessage(var seq, List<String> path) {
    var map = {
      'seq': seq,
      'path': path
    };
    var message = JSON.encode(map);
    _socket.add(message);
    return _completer.future;
  }
}

abstract class VmServiceRequestHelper {
  final Uri uri;
  final HttpClient client;

  VmServiceRequestHelper(String url) :
      uri = Uri.parse(url),
      client = new HttpClient();

  Future makeRequest() {
    print('** GET: $uri');
    return client.getUrl(uri)
      .then((HttpClientRequest request) => request.close())
      .then((HttpClientResponse response) {
        return response
            .fold(new BytesBuilder(), (b, d) => b..add(d))
            .then((builder) {
              return _requestCompleted(builder.takeBytes(), response);
            });
      }).catchError((error) {
        onRequestFailed(error);
      });
  }

  Future _requestCompleted(List<int> data, HttpClientResponse response) {
    Expect.equals(200, response.statusCode, 'Invalid HTTP Status Code');
    var replyAsString;
    try {
      replyAsString = UTF8.decode(data);
    } catch (e) {
      onRequestFailed(e);
      return null;
    }
    print('** Response: $replyAsString');
    var reply;
    try {
      reply = JSON.decode(replyAsString);
    } catch (e) {
      onRequestFailed(e);
      return null;
    }
    if (reply is! Map) {
      onRequestFailed('Reply was not a map: $reply');
      return null;
    }
    if (reply['type'] == null) {
      onRequestFailed('Reply does not contain a type key: $reply');
      return null;
    }
    var r;
    try {
      r = onRequestCompleted(reply);
    } catch (e) {
      r = onRequestFailed('Test callback failed: $e');
    }
    return r;
  }

  Future onRequestFailed(dynamic error) {
    Expect.fail('Failed to make request: $error');
  }

  Future onRequestCompleted(Map response);
}

class TestLauncher {
  final String script;
  Process process;

  TestLauncher(this.script);

  String get scriptPath {
    var dartScript = Platform.script.toFilePath();
    var splitPoint = dartScript.lastIndexOf(Platform.pathSeparator);
    var scriptDirectory = dartScript.substring(0, splitPoint);
    return scriptDirectory + Platform.pathSeparator + script;
  }

  Future<int> launch() {
    String dartExecutable = Platform.executable;
    print('** Launching $scriptPath');
    return Process.start(dartExecutable,
                         ['--enable-vm-service:0', scriptPath]).then((p) {

      Completer completer = new Completer();
      process = p;
      var portNumber;
      var blank;
      var first = true;
      process.stdout.transform(UTF8.decoder)
                    .transform(new LineSplitter()).listen((line) {
        if (line.startsWith('VMService listening on port ')) {
          RegExp portExp = new RegExp(r"\d+");
          var port = portExp.stringMatch(line);
          portNumber = int.parse(port);
        }
        if (line == '') {
          // Received blank line.
          blank = true;
        }
        if (portNumber != null && blank == true && first == true) {
          completer.complete(portNumber);
          // Stop repeat completions.
          first = false;
          print('** Signaled to run test queries on $portNumber');
        }
        print(line);
      });
      process.stderr.transform(UTF8.decoder)
                    .transform(new LineSplitter()).listen((line) {
        print(line);
      });
      process.exitCode.then((code) {
        Expect.equals(0, code, 'Launched dart executable exited with error.');
      });
      return completer.future;
    });
  }

  void requestExit() {
    print('** Requesting script to exit.');
    process.stdin.add([32, 13, 10]);
  }
}

class IsolateListTester {
  final Map isolateList;

  IsolateListTester(this.isolateList) {
    // The reply is an IsolateList.
    Expect.equals('IsolateList', isolateList['type'], 'Not an IsolateList.');
  }

  void checkIsolateCount(int n) {
    Expect.equals(n, isolateList['members'].length, 'Isolate count not $n');
  }

  void checkIsolateIdExists(String id) {
    var exists = false;
    isolateList['members'].forEach((isolate) {
      if (isolate['id'] == id) {
        exists = true;
      }
    });
    Expect.isTrue(exists, 'No isolate with id: $id');
  }

  String getIsolateId(int index) {
    return isolateList['members'][index]['id'];
  }
}

class ClassTableHelper {
  final Map classTable;

  ClassTableHelper(this.classTable) {
    Expect.equals('ClassList', classTable['type'], 'Not a ClassTable.');
  }

  bool classExists(String user_name) {
    List members = classTable['members'];
    for (var i = 0; i < members.length; i++) {
      Map klass = members[i];
      if (klass['user_name'] == user_name) {
        return true;
      }
    }
    return false;
  }

  String classId(String user_name) {
    List members = classTable['members'];
    for (var i = 0; i < members.length; i++) {
      Map klass = members[i];
      if (klass['user_name'] == user_name) {
        return klass['id'];
      }
    }
    return null;
  }
}

class FieldRequestHelper extends VmServiceRequestHelper {
  FieldRequestHelper(port, isolate_id, field_id) :
      super('http://127.0.0.1:$port/$isolate_id/$field_id');
  Map field;
  onRequestCompleted(Map reply) {
    Expect.equals('Field', reply['type']);
    field = reply;
    return new Future.value(this);
  }
}

class ClassFieldRequestHelper extends VmServiceRequestHelper {
  final List<String> fieldNames;
  int port_;
  String isolate_id_;
  ClassFieldRequestHelper(port, isolate_id, class_id, this.fieldNames) :
      super('http://127.0.0.1:$port/$isolate_id/$class_id') {
    port_ = port;
    isolate_id_ = isolate_id;
  }
  final Map<String, Map> fields = new Map<String, Map>();

  onRequestCompleted(Map reply) {
    Expect.equals('Class', reply['type']);
    List<Map> class_fields = reply['fields'];
    List<Future> requests = new List<Future>();
    fieldNames.forEach((fn) {
      class_fields.forEach((f) {
        if (f['user_name'] == fn) {
          var request = new FieldRequestHelper(port_, isolate_id_, f['id']);
          requests.add(request.makeRequest());
        }
      });
    });
    return Future.wait(requests).then((a) {
      a.forEach((FieldRequestHelper field) {
        fields[field.field['user_name']] = field.field;
      });
      return this;
    });
  }
}
