### codetube
    Copyright (C) 2011 payload payload@lavabit.com
    Copyright (C) 2011 dodo dodo.the.last@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>
###

Path = require('path')
gt = require('gettext')
buffertools = require('buffertools')
{ concat_buffers } = require('bufferstream')
Project = require('./models/project')
appconfig = require('./appconfig')
config = require('./config')

class Proxy
    constructor: () ->

    to_git_data: (str) =>
        len = 4 + str.length
        hex = len.toString(16)
        while hex.length < 4
            hex = "0" + hex
        console.log({git:hex+str}) if config.debug
        new Buffer(hex+str, 'binary')

    request: (buffer, stream) => # stream should allready listen on buffer data
        begin = buf: new Buffer(0)
        buffer.split "\00", (chunk, token) =>
            token = new Buffer(token, 'binary')
            begin.buf = concat_buffers(begin.buf, chunk, token)
            return unless buffertools.indexOf.call(chunk, "host=") is 0
            begin = begin.buf

            # cut out request packet
            git = buffertools.indexOf.call(begin, "git-")
            packet = new Buffer(begin.length - git)
            begin.copy(packet, 0, git)
            # buffered data
            buf = new Buffer(0)
            if git > 4 # git packet prefix
                buf = new Buffer(git - 4)
                begin.copy(buf, 0, 0, git - 4)
            # parse request packet
            packet = packet.toString()
            sp = packet.indexOf(" ")
            cmd = packet[0 ... sp]
            host = packet.indexOf("\00host=", sp)
            req = packet[sp+2 ... host]
            @map_paths req, (err, path) =>
                path = "" if err
                cmd = "#{cmd} /#{path}\00host=#{config.gitdaemon.address}\00"
                buffer.buffer = concat_buffers(buf, @to_git_data(cmd), buffer.buffer)
                buffer.disable("\00")
                buffer.setSize('none') unless buffer.splitters.length

    # stream should already listen on buffer data
    response: (buffer, name) =>
        buffer.split "0000", (begin, token) =>
            buf = concat_buffers(begin, new Buffer(token, 'binary'))
            buffer.emit 'data', buf
        buffer.split "0008NAK\n", (begin, token) =>
            buf = concat_buffers(begin, new Buffer(token, 'binary'))
            data = [
                gt._s(gt._("hello %1"), name)
                gt._s(gt._("welcome to %1"), config.name)
                ""]
            data[2] += "-" for i in [1..Math.max(data[0].length,data[1].length)]
            for chunk in data
                buf = concat_buffers(buf, @to_git_data("\02#{chunk}\n"))
            buffer.buffer = concat_buffers(buf, buffer.buffer)
            # it is okay to disable everything here
            buffer.disable("0000", "0008NAK\n")
            buffer.setSize('none') unless buffer.splitters.length

    # maps a repo name to the repo hash path
    map_paths: (req, callback) =>
        req = req[...-4] # without .git
        # filter out with project repository the requester is referring to
        # i.e. :userid/:projectid.source or :userid/:projectid.wiki
        repo = "source"
        for name in appconfig.repositories
            continue unless req[req.length-name.length-1] is "."
            if req[-name.length ..] is name
                req = req[...-name.length-1]
                repo = name
                break
        [userid, projectid] = req.split '/'
        Project.fetch userid, projectid, (err, user, project) ->
            return callback(err) if err
            callback(null, Path.join(project.hash, repo))

module.exports = Proxy

