var extract = require('../helpers/extract.js');
var pushToPull = require('push-to-pull');
var deframer = pushToPull(require('../lib/pkt-line.js').deframer);
var framer = pushToPull(require('../lib/pkt-line.js').framer);
var writable = require('../lib/writable.js');

module.exports = tcpTransport;
function tcpTransport(platform) {
  var tcp = extract(platform, "tcp");
  var agent = extract(platform, "agent");

  return setup;

  // opts.hostname - host to connect to (github.com)
  // opts.pathname - path to repo (/creationix/conquest.git)
  // opts.port - override default port (9418)
  function setup(opts) {
    if (!opts.hostname) throw new TypeError("hostname is a required option");
    if (!opts.pathname) throw new TypeError("pathname is a required option");
    opts.port = opts.port ? opts.port | 0 : 9418;

    var read, abort, write;

    return {
      discover: discover,
      negotiate: negotiate,
      close: close
    };

    function connect(callback) {
      return tcp.connect(opts.port, opts.hostname, function (err, socket) {
        if (err) return callback(err);
        var input = deframer(socket);
        if (opts.trace) input = opts.trace("input", input);

        read = input.read;
        abort = input.abort;
        write = writable(abort);
        var output = write;
        if (opts.trace) output = opts.trace("output", output);
        output = framer(output);
        socket.sink(output)(function (err) {
          throw err;
          // TODO: handle this better somehow
          // maybe allow writable streams
        });
        callback();
      });
    }

    // Send initial git-upload-pack request
    // outputs refs and caps
    function discover(callback) {
      if (!callback) return discover.bind(this);
      var refs = {};
      var caps = null;
      connect(function (err) {
        if (err) return callback(err);

        write("git-upload-pack " + opts.pathname + "\0host=" + opts.hostname + "\0");
        read(onLine);

        function onLine(err, line) {
          if (err) return callback(err);
          if (line === null) {
            return callback(null, {
              refs: refs,
              caps: caps
            });
          }
          line = line.trim();
          if (!caps) line = pullCaps(line);
          var index = line.indexOf(" ");
          refs[line.substr(index + 1)] = line.substr(0, index);
          read(onLine);
        }

        function pullCaps(line) {
          var index = line.indexOf("\0");
          caps = {};
          line.substr(index + 1).split(" ").map(function (cap) {
            var pair = cap.split("=");
            caps[pair[0]] = pair[1] || true;
          });
          return line.substr(0, index);
        }
        
      });
    }

    function negotiate(callback) {
      if (!callback) return negotiate.bind(this);
      if (!read) return callback(new Error("Can't negotiate till connected"));
      throw new Error("TODO: Implement tcp negotiate");
    }

    function close(callback) {
      if (!callback) return close.bind(this);
      if (write) {
        write(null);
        write();
      }
      if (abort) {
        return abort(callback);  
      }
      callback();
    }

  }

};


@@ -1767,51 +1767,35 @@
     
-var refs = %7B%7D;%0A      var caps = null;%0A     
+if (!read) %7B%0A        return
  con
@@ -1808,32 +1808,34 @@
 unction (err) %7B%0A
+  
         if (err)
@@ -1857,19 +1857,118 @@
 k(err);%0A
-%0A
   
+        return discover(callback);%0A        %7D);%0A      %7D%0A      var refs = %7B%7D;%0A      var caps = null;%0A%0A
       wr
@@ -2039,26 +2039,24 @@
 me + %22%5C0%22);%0A
-  
       read(o
@@ -2062,34 +2062,32 @@
 onLine);%0A%0A      
-  
 function onLine(
@@ -2091,34 +2091,32 @@
 ne(err, line) %7B%0A
-  
         if (err)
@@ -2142,26 +2142,24 @@
 r);%0A        
-  
 if (line ===
@@ -2173,26 +2173,24 @@
 %7B%0A          
- 
- 
 return callb
@@ -2201,18 +2201,16 @@
 null, %7B%0A
-  
         
@@ -2233,26 +2233,24 @@
             
-  
 caps: caps%0A 
@@ -2250,34 +2250,32 @@
  caps%0A          
- 
- 
 %7D);%0A          %7D%0A
@@ -2266,30 +2266,26 @@
 %7D);%0A        
-  %7D%0A  
+%7D%0A
         line
@@ -2296,26 +2296,24 @@
 ine.trim();%0A
-  
         if (
@@ -2342,34 +2342,32 @@
 (line);%0A        
-  
 var index = line
@@ -2377,26 +2377,24 @@
 dexOf(%22 %22);%0A
-  
         refs
@@ -2439,26 +2439,24 @@
 (0, index);%0A
-  
         read
@@ -2471,23 +2471,19 @@
 ;%0A      
-  
 %7D%0A%0A
-  
       fu
@@ -2510,26 +2510,24 @@
 ) %7B%0A        
-  
 var index = 
@@ -2550,26 +2550,24 @@
 %22);%0A        
- 
- 
 caps = %7B%7D;%0A 
@@ -2561,26 +2561,24 @@
  caps = %7B%7D;%0A
-  
         line
@@ -2634,26 +2634,24 @@
 %7B%0A          
-  
 var pair = c
@@ -2671,26 +2671,24 @@
 ;%0A          
- 
- 
 caps%5Bpair%5B0%5D
@@ -2708,34 +2708,32 @@
 %7C true;%0A        
-  
 %7D);%0A          re
@@ -2724,26 +2724,24 @@
 %7D);%0A        
- 
- 
 return line.
@@ -2758,26 +2758,24 @@
 index);%0A
-  
       %7D%0A
         
@@ -2770,27 +2770,8 @@
   %7D%0A
-        %0A      %7D);%0A
     

Clean up nesting a bit in tcp discover