#!/usr/bin/env python

import os.path

from twisted.internet import reactor
import twisted.python.log
from twisted.web.server import Site
from twisted.web.static import File

import txroutes


def return404(request):
    request.setResponseCode(404)
    return '<html><head><title>404 Not Found</title></head><body><h1>Not found</h1></body></html>'

def get_package_path(package, version=None, want_file=False):
    path = os.path.join(os.path.dirname(__file__), 'packages', package)

    if version:
        path = os.path.join(path, version)

        if want_file:
            path = os.path.join(path, '%s-%s.tar.gz' % (package, version))

    return path


class Controller(object):

    def get_index(self, request):
        return '<html><head><title>simplepypi</title></head><body><a href="/packages">packages</a></body></html>'

    def post_index(self, request):
        name = request.args.get('name', [None])[0]
        version = request.args.get('version', [None])[0]
        action = request.args.get(':action', [None])[0]
        content = request.args.get('content', [None])[0]

        if name is not None and version is not None and content is not None \
                and action == 'file_upload':

            name = name.lower()

            path = get_package_path(name, version, want_file=True)

            if not os.path.exists(os.path.dirname(path)):
                os.makedirs(os.path.dirname(path))

            fd = open(path, 'wb')
            fd.write(content)
            fd.close()

        return ''

    def get_pypi(self, request):
        body = '<html><body>\n'

        packages_path = os.path.join(os.path.dirname(__file__), 'packages')
        packages_list = os.listdir(packages_path)

        for each in packages_list:
            versions_path = os.path.join(packages_path, each)
            versions_list = os.listdir(versions_path)
            versions_list.sort()

            if len(versions_list) > 0:
                body += '<a href="/packages/%(package)s/%(version)s/%(package)s-%(version)s.tar.gz">%(package)s-%(version)s</a>' % {'package': each, 'version': versions_list[-1]}

        body += '</body></html>'

        return body.encode('utf8')

    def package(self, request, package):
        package = package.lower()

        package_path = get_package_path(package)

        if not os.path.exists(package_path):
            return return404(request)

        versions = os.listdir(package_path)
        versions.sort()

        if len(versions) == 0:
            return return404(request)

        if os.path.exists(package_path):
            body = '<html><body><a href="/packages/%(package)s/%(version)s/%(package)s-%(version)s.tar.gz">%(package)s-%(version)s.tar.gz</a></body></html>' % {'package': package, 'version': versions[-1]}
            return body.encode('utf8')

        else:
            return return404(request)

    def package_and_version(self, request, package, version):
        package = package.lower()

        path = get_package_path(package, version, want_file=True)

        if os.path.exists(path):
            body = '<html><body><a href="/packages/%(package)s/%(version)s/%(package)s-%(version)s.tar.gz">%(package)s-%(version)s.tar.gz</a></body></html>' % {'package': package, 'version': version}
            return body.encode('utf8')

        else:
            return return404(request)

def set_up_server(port):
    observer = twisted.python.log.PythonLoggingObserver()
    observer.start()

    dispatcher = txroutes.Dispatcher()
    controller = Controller()

    dispatcher.connect('get_index', '/', controller=controller,
            action='get_index', conditions=dict(method=['GET']))

    dispatcher.connect('post_index', '/', controller=controller,
            action='post_index', conditions=dict(method=['POST']))

    dispatcher.connect('get_pypi', '/pypi/', controller=controller,
            action='get_pypi', conditions=dict(method=['GET']))

    dispatcher.connect('package', '/pypi/{package}/', controller=controller,
            action='package')

    dispatcher.connect('package_and_version', '/pypi/{package}/{version}',
            controller=controller, action='package_and_version')

    package_path = os.path.join(os.path.dirname(__file__), 'packages')
    dispatcher.putChild('packages', File(package_path))

    factory = Site(dispatcher)
    reactor.listenTCP(port, factory)

    print 'Running on %d' % port
    reactor.run()

if __name__ == '__main__':
    set_up_server(8000)
