 
     parse_line: (line) ->
         if @should_parse_data
-            if @readbytes >= @datasize and line is ".\n"
+            if @fh.readbytes < @fh.datasize
+                @fh.readbytes += Buffer.byteLength(line)
+                # remove trailing newline if necessary
+                if @fh.readbytes == @fh.datasize + 1 and line.slice(-1) is "\n"
+                    line = line.slice(0, -1)
+                @fh.write(line)
+            if @fh.readbytes >= @fh.datasize
                 @should_parse_data = false
-                fs.closeSync @fd
-                @open_in_atom()
-            else if @readbytes < @datasize
-                @readbytes += Buffer.byteLength(line)
-                if @readbytes > @datasize and line.slice(-1) is "\n"
-                    line = line.slice(0, -1)
-                fs.writeSync(@fd, line)
+                @fh.open_in_atom()
+
+        else if line.match /open\n/
+            @fh = new FileHandler(@)
+            @nconn += 1
+
         else
             m = line.match /([a-z\-]+?)\s*:\s*(.*?)\s*$/
             if m and m[2]?
-                @settings[m[1]] = m[2]
+                @fh.settings[m[1]] = m[2]
                 switch m[1]
                     when "token"
-                        @token = m[2]
+                        @fh.token = m[2]
                     when "data"
-                        @datasize = parseInt(m[2],10)
+                        @fh.datasize = parseInt(m[2],10)
                         @should_parse_data = true
                     when "display-name"
-                        @displayname = m[2]
-                        @remoteAddress = @displayname.split(":")[0]
-                        @basename = path.basename(@displayname.split(":")[1])
-                        @make_tempfile()
-
-    open_in_atom: ->
-        console.log "[ratom] opening #{@tempfile}"
-        # register events
-        atom.workspace.open(@tempfile, activatePane:true).then (editor) =>
-            @handle_connection(editor)
-
-    handle_connection: (editor) ->
-        atom.focus()
-        buffer = editor.getBuffer()
-        @subscriptions = new CompositeDisposable
-        @subscriptions.add buffer.onDidSave(@save)
-        @subscriptions.add buffer.onDidDestroy(@close)
+                        @fh.displayname = m[2]
+                        @fh.remoteAddress = m[2].split(":")[0]
+                        @fh.basename = path.basename(m[2].split(":")[1])
+                        @fh.make_tempfile()
 
     send: (cmd) ->
-        if @online
-            @socket.write cmd+"\n"
+        @socket.write cmd+"\n"
 
-    save: =>
-        if not @online
-            console.log "[ratom] Error saving #{path.basename @tempfile} to #{@remoteAddress}"
-            status-message.display "Error saving #{path.basename @tempfile} to #{@remoteAddress}", 2000
-            return
-        console.log "[ratom] saving #{path.basename @tempfile} to #{@remoteAddress}"
-        status-message.display "Saving #{path.basename @tempfile} to #{@remoteAddress}", 2000
-        @send "save"
-        @send "token: #{@token}"
-        data = fs.readFileSync(@tempfile)
-        @send "data: " + Buffer.byteLength(data)
-        @socket.write data
-        @send ""
-
-    close: =>
-        console.log "[ratom] closing #{path.basename @tempfile}"
-        if @online
+    close: ->
+        @nconn -= 1
+        console.log @nconn
+        if @alive and @nconn == 0
             @online = false
             @send "close"
             @send ""
             @socket.end()
-        @subscriptions.dispose()
 
 
 module.exports =

randomstring = require './randomstring'
status-message = require './status-message'

class Session
    should_parse_data: false
    readbytes: 0
    settings: {}

    constructor: (socket) ->
        @socket = socket
        @online = true
        socket.on "data", (chunk) =>
            @parse_chunk(chunk)
        socket.on "close", =>
            @online = false

    make_tempfile: ()->
        @tempfile = path.join(os.tmpdir(), randomstring(10), @basename)

        dirname = path.dirname(@tempfile)
        mkdirp.sync(dirname)
        @fd = fs.openSync(@tempfile, 'w')

    write: (str) ->
        fs.writeSync(@fd, str)

    open_in_atom: ->
        fs.closeSync @fd
        console.log "[ratom] opening #{@tempfile}"
        # register events
        atom.workspace.open(@tempfile, activatePane:true).then (editor) =>
            @handle_connection(editor)

    handle_connection: (editor) ->
        atom.focus()
        buffer = editor.getBuffer()
        @subscriptions = new CompositeDisposable
        @subscriptions.add buffer.onDidSave(@save)
        @subscriptions.add buffer.onDidDestroy(@close)

    save: =>
        if not @session.alive
            console.log "[ratom] Error saving #{path.basename @tempfile} to #{@remoteAddress}"
            status-message.display "Error saving #{path.basename @tempfile} to #{@remoteAddress}", 2000
            return
        console.log "[ratom] saving #{path.basename @tempfile} to #{@remoteAddress}"
        status-message.display "Saving #{path.basename @tempfile} to #{@remoteAddress}", 2000
        @session.send "save"
        @session.send "token: #{@token}"
        data = fs.readFileSync(@tempfile)
        @session.send "data: " + Buffer.byteLength(data)
        @session.send data

    close: =>
        console.log "[ratom] closing #{path.basename @tempfile}"
        @session.close()
        @subscriptions.dispose()

class Session
    should_parse_data: false
    nconn: 0

    constructor: (socket) ->
        @socket = socket
        @alive = true
        socket.on "data", (chunk) =>
            @parse_chunk(chunk)
        socket.on "close", =>
            @alive = false
            console.log "[ratom] connection lost!"
            status-message.display "Connection lost!", 5000

    parse_chunk: (chunk) ->
        if chunk
