#!mojo mojo:dart_content_handler
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:core';
import 'dart:typed_data';

import 'package:mojo/application.dart';
import 'package:mojo/bindings.dart';
import 'package:mojo/core.dart';
import 'package:mojo/mojo/network_error.mojom.dart';
import 'package:mojo_services/mojo/files/file.mojom.dart' as files;
import 'package:mojo_services/mojo/files/types.mojom.dart' as files;
import 'package:mojo_services/mojo/net_address.mojom.dart';
import 'package:mojo_services/mojo/network_service.mojom.dart';
import 'package:mojo_services/mojo/tcp_bound_socket.mojom.dart';
import 'package:mojo_services/mojo/tcp_connected_socket.mojom.dart';
import 'package:mojo_services/mojo/terminal/terminal_client.mojom.dart';

void ignoreFuture(Future f) {
  f.catchError((e) {});
}

NetAddress makeIPv4NetAddress(List<int> addr, int port) {
  var rv = new NetAddress();
  rv.family = NetAddressFamily_IPV4;
  rv.ipv4 = new NetAddressIPv4();
  rv.ipv4.addr = new List<int>.from(addr);
  rv.ipv4.port = port;
  return rv;
}

void fputs(files.File f, String s) {
  ignoreFuture(f.write((s + '\n').codeUnits, 0, files.Whence_FROM_CURRENT));
}

// Connects the terminal |File| and the socket.
// TODO(vtl):
// * Error handling: both connection/socket errors and terminal errors.
// * Relatedly, we should listen for _socketSender's peer being closed (also
//   _socket, I guess).
// * Handle the socket send pipe being full (currently, we assume it's never
//   full).
class Connector {
  final Application _application;
  final files.FileProxy _terminal;
  TcpConnectedSocketProxy _socket;
  MojoDataPipeProducer _socketSender;
  MojoDataPipeConsumer _socketReceiver;
  MojoEventStream _socketReceiverEventStream;
  final ByteData _readBuffer;
  final ByteData _writeBuffer;

  // TODO(vtl): Don't just hard-code buffer sizes.
  Connector(this._application, this._terminal)
      : _readBuffer = new ByteData(16 * 1024),
        _writeBuffer = new ByteData(16 * 1024);

  Future connect(NetAddress remote_address) async {
    var networkService = new NetworkServiceProxy.unbound();
    _application.connectToService('mojo:network_service', networkService);

    NetAddress local_address = makeIPv4NetAddress([0, 0, 0, 0], 0);
    var boundSocket = new TcpBoundSocketProxy.unbound();
    await networkService.ptr.createTcpBoundSocket(local_address, boundSocket);
    await networkService.close();

    var sendDataPipe = new MojoDataPipe();
    _socketSender = sendDataPipe.producer;
    var receiveDataPipe = new MojoDataPipe();
    _socketReceiver = receiveDataPipe.consumer;
    _socket = new TcpConnectedSocketProxy.unbound();
    await boundSocket.ptr.connect(remote_address, sendDataPipe.consumer,
        receiveDataPipe.producer, _socket);
    await boundSocket.close();

    // Set up reading from the terminal.
    _startReadingFromTerminal();

    // Set up reading from the socket.
    _socketReceiverEventStream = new MojoEventStream(_socketReceiver.handle);
    _socketReceiverEventStream.listen(_onSocketReceiverEvent);
  }

  void _startReadingFromTerminal() {
    // TODO(vtl): Handle terminal errors.
    _terminal.ptr
        .read(_writeBuffer.lengthInBytes, 0, files.Whence_FROM_CURRENT)
        .then(_onReadFromTerminal);
  }

  void _onReadFromTerminal(files.FileReadResponseParams p) {
    if (p.error != files.Error_OK) {
      // TODO(vtl): Do terminal errors.
      return;
    }

    // TODO(vtl): Temporary hack: echo, since we don't have built-in echo
    // support.
    ignoreFuture(
        _terminal.ptr.write(p.bytesRead, 0, files.Whence_FROM_CURRENT));

    // TODO(vtl): Verify that |bytesRead.length| is within the expected range.
    for (var i = 0, j = 0; i < p.bytesRead.length; i++, j++) {
      // TODO(vtl): Temporary hack: Translate \r to \n, since we don't have
      // built-in support for that.
      if (p.bytesRead[i] == 13) {
        _writeBuffer.setUint8(i, 10);
      } else {
        _writeBuffer.setUint8(i, p.bytesRead[i]);
      }
    }

    // TODO(vtl): Handle the send data pipe being full (or closed).
    _socketSender
        .write(new ByteData.view(_writeBuffer.buffer, 0, p.bytesRead.length));

    _startReadingFromTerminal();
  }

  void _onSocketReceiverEvent(List<int> event) {
    var mojoSignals = new MojoHandleSignals(event[1]);
    var shouldClose = false;
    if (mojoSignals.isReadable) {
      var numBytesRead = _socketReceiver.read(_readBuffer);
      if (_socketReceiver.status.isOk) {
        assert(numBytesRead > 0);
        _terminal.ptr.write(_readBuffer.buffer.asUint8List(0, numBytesRead), 0,
            files.Whence_FROM_CURRENT);
        _socketReceiverEventStream.enableReadEvents();
      } else {
        shouldClose = true;
      }
    } else if (mojoSignals.isPeerClosed) {
      shouldClose = true;
    } else {
      throw 'Unexpected handle event: $mojoSignals';
    }
    if (shouldClose) {
      _socketReceiverEventStream.close();
      _socketReceiverEventStream = null;
      fputs(_terminal.ptr, 'Connection closed.');
    }
  }
}

class TerminalClientImpl implements TerminalClient {
  TerminalClientStub _stub;
  Application _application;
  String _resolvedUrl;

  TerminalClientImpl(
      this._application, this._resolvedUrl, MojoMessagePipeEndpoint endpoint) {
    _stub = new TerminalClientStub.fromEndpoint(endpoint, this);
  }

  @override
  void connectToTerminal(files.FileProxy terminal) {
    var url = Uri.parse(_resolvedUrl);
    NetAddress remote_address;
    try {
      remote_address = _getNetAddressFromUrl(url);
    } catch (e) {
      fputs(terminal.ptr, 'HALP: Add a query: ?host=<host>&port=<port>\n'
          '(<host> must be "localhost" or n1.n2.n3.n4)\n\n'
          'Got query parameters:\n' + url.queryParameters.toString());
      ignoreFuture(terminal.close());
      return;
    }

    // TODO(vtl): Currently, we only do IPv4, so this should work.
    fputs(terminal.ptr, 'Connecting to: ' +
        remote_address.ipv4.addr.join('.') +
        ':' +
        remote_address.ipv4.port.toString() +
        '...');

    var connector = new Connector(_application, terminal);
    connector.connect(remote_address);
  }

  // Note: May throw all sorts of things.
  static NetAddress _getNetAddressFromUrl(Uri url) {
    var params = url.queryParameters;
    var host = params['host'];
    return makeIPv4NetAddress(
        (host == 'localhost') ? [127, 0, 0, 1] : Uri.parseIPv4Address(host),
        int.parse(params['port']));
  }
}

class NetcatApplication extends Application {
  NetcatApplication.fromHandle(MojoHandle handle) : super.fromHandle(handle);

  @override
  void acceptConnection(String requestorUrl, String resolvedUrl,
      ApplicationConnection connection) {
    connection.provideService(TerminalClientName,
        (endpoint) => new TerminalClientImpl(this, resolvedUrl, endpoint));
  }
}

main(List args) {
  MojoHandle appHandle = new MojoHandle(args[0]);
  String url = args[1];
  new NetcatApplication.fromHandle(appHandle)
    ..onError = (() {
      assert(MojoHandle.reportLeakedHandles());
    });
}
