#!/usr/bin/env python

import argparse
import sys
import os
import ramen

parser = argparse.ArgumentParser(prog='ramen')

subparsers = parser.add_subparsers(help='ramen management script', dest='command')

s = subparsers.add_parser('run', help='runs application server')
s.add_argument('-p', '--port', type=int, help='port number to run server at')
s.add_argument('-r', '--ports', type=int, nargs=2, help='ports range number to run server at')

d = subparsers.add_parser('dashboard', help='runs dashboard management server')
d.add_argument('-p', '--port', type=int, default=8899, help='port number to run server at')

g = subparsers.add_parser('gen', help='generates something')
g.add_argument('type', help='type of generating something')
g.add_argument('name', help='name of generating something')
g.add_argument('fields', nargs='*', help='args of generating something')

i = subparsers.add_parser('init', help='initialize empty project')
i.add_argument('name', help='name of project')


sys.path.append(os.getcwd())

from ramen.boot import Bootstrap
from multiprocessing import Pool

def daemonize(port, settings):
    return Bootstrap(port, **settings)

def server(**kw):
    from settings import settings

    port = kw.get('port')
    rng = kw.get('ports', [8888,8890])

    if settings.get('debug'):
        daemonize(port, settings)
    else:
        if not port:
            s,f = rng[0], rng[1]+1
            pool = Pool(f-s)
            pool.map(daemonize, range(s,f), settings)
            pool.join()
        else:
            daemonize(port, settings)


def dashboard(port=8899):
    t = time.time()
    s = ''

    for x in xrange(1000000):
        s = s+'X'

    del s
    print 'DONE', time.time() - t

    print 'Running dashboard, port:', port


def generate(type, name, fields):
    print 'generating stuff'


def init(name):

    def _make_writeable(filename):
        """
        Make sure that the file is writeable. Useful if our source is
        read-only.

        """
        import stat
        if sys.platform.startswith('java'):
            # On Jython there is no os.access()
            return
        if not os.access(filename, os.W_OK):
            st = os.stat(filename)
            new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
            os.chmod(filename, new_permissions)

    def copy_helper(file_or_project, name, directory):
        """
        Copies either a Django application layout template or a Django project
        layout template into the specified directory.

        """
        # style -- A color style object (see django.core.management.color).
        # app_or_project -- The string 'app' or 'project'.
        # name -- The name of the application or project.
        # directory -- The directory to which the layout template should be copied.
        # other_name -- When copying an application layout, this should be the name
        #               of the project.
        import re
        import shutil
        other = {'project': 'file', 'file': 'project'}[file_or_project]
        if not re.search(r'^[_a-zA-Z]\w*$', name): # If it's not a valid directory name.
            # Provide a smart error message, depending on the error.
            if not re.search(r'^[_a-zA-Z]', name):
                message = 'make sure the name begins with a letter or underscore'
            else:
                message = 'use only numbers, letters and underscores'
            raise Exception("%r is not a valid %s name. Please %s." % (name, file_or_project, message))
        top_dir = os.path.join(directory, name)
        try:
            os.mkdir(top_dir)
        except OSError, e:
            raise Exception(e)

        # Determine where the app or project templates are. Use
        # django.__path__[0] because we don't know into which directory
        # django has been installed.
        template_dir = os.path.join(ramen.__path__[0], 'templates', file_or_project)

        for d, subdirs, files in os.walk(template_dir):
            relative_dir = d[len(template_dir)+1:].replace(file_or_project, name)
            if relative_dir:
                os.mkdir(os.path.join(top_dir, relative_dir))
            for subdir in subdirs[:]:
                if subdir.startswith('.'):
                    subdirs.remove(subdir)
            for f in files:
                if not (f.endswith('.py') or f.endswith('.html')):
                    # Ignore .pyc, .pyo, .py.class etc, as they cause various
                    # breakages.
                    continue
                path_old = os.path.join(d, f)
                path_new = os.path.join(top_dir, relative_dir, f.replace(file_or_project, name))
                fp_old = open(path_old, 'r')
                fp_new = open(path_new, 'w')
                fp_new.write(fp_old.read().replace('{{ %s_name }}' % file_or_project, name))
                fp_old.close()
                fp_new.close()
                try:
                    shutil.copymode(path_old, path_new)
                    _make_writeable(path_new)
                except OSError:
                    sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))

    copy_helper('project', name, os.getcwd())

commands = {
    'run': server,
    'dashboard': dashboard,
    'gen': generate,
    'init': init
}

args = vars(parser.parse_args())
command = args.pop('command')

commands[command](**args)
