#!/usr/bin/env python
# Copyright 2007 Robin Gottfried <google@kebet.cz>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# @author Robin Gottfried <google@kebet.cz>
# part of gap project (https://github.com/czervenka/gap)

__author__ = 'Robin Gottfried <google@kebet.cz>'
import os
import sys
from os.path import join, realpath, dirname, exists
import stat
import re
from copy import deepcopy
from pkg_resources import resource_filename
from shutil import copytree, copyfile


TEMPLATES_DIR = 'templates'

CONTEXT = {}


def _chmod_exec(path):
    with open(path, 'r') as fd:
        mode = os.fstat(fd.fileno()).st_mode
        os.fchmod(fd.fileno(), stat.S_IMODE(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH))

def _render_inplace(path, context={}):
    context.update(CONTEXT)

    data = re.sub(r'{<\s*([^}]+?)\s*>}', lambda match: context.get(match.group(1), ''), open(path, 'rb').read())
    open(path, 'wb').write(data)

def _copy_resource(resource, destination, context={}):
    resource_path = resource_filename('gap', resource)
    if os.path.isdir(resource_path):
        copytree(resource_path, destination)
        for root, dirs, files in os.walk(destination, topdown=False):
            for name in files:
                _render_inplace(join(root, name), context)
    else:
        copyfile(resource_path, destination)
        _render_inplace(destination, context)


def start_project(project_name, path=None):
    context = deepcopy(CONTEXT)
    context['application_id'] = project_name
    if path is None:
        path = join(realpath(os.path.curdir), project_name)
    else:
        path = join(realpath(path), project_name)
    if not exists(dirname(path)):
        _error('Path %r does not exit.' % path)
    if exists(path):
        _error('Path %r already exists.' % path)
    os.mkdir(path)
    _copy_resource(join(TEMPLATES_DIR, 'src'), join(path, 'src'), context)
    _copy_resource(join(TEMPLATES_DIR, 'bin'), join(path, 'bin'), context)
    _copy_resource(join(TEMPLATES_DIR, 'requirements.gip'), join(path, 'requirements.gip'), context)
    for root, dirs, files in os.walk(join(path, 'bin')):
        for file_ in files:
            _chmod_exec(join(root, file_))
    _copy_resource(join(TEMPLATES_DIR, 'tests'), join(path, 'tests'), context)
    _chmod_exec(join(path, 'tests', 'run_tests.py'))
    os.mkdir(join(path, '.tmp'))
    from gap.utils import gip
    gip.update_symlinks(join(path, 'src', 'lib'))


def start_app(app_name):
    context = deepcopy(CONTEXT)
    context['app_name'] = app_name
    path = join(os.path.curdir, 'src', 'app', app_name)
    if exists(path):
        _error('Path %r already exists.' % path)
    if not exists(dirname(path)):
        _error('Path %r does not exist. Are you sure you are in root of the project?' % path)
    _copy_resource(join(TEMPLATES_DIR, 'module'), path, context)

def install_from_git(repo_uri):
    if exists('src/app.yaml'):
        branch = 'master'
        if '#' in repo_uri:
            repo_uri, branch = repo_uri.rsplit('#', 1)
        cmd = 'git archive --remote=%r %r | tar x' % (repo_uri, branch)
        print cmd
        os.system(cmd)
    else:
        _error('Seems that we are not in a project root.')


def _error(message, exit=1):
    print 'E: %s' % message
    if exit:
        sys.exit(exit)


def _usage():
    print '''Usage:
    gap start-project <project_name>  (creates new project in current directory)
    gap start-app <app_name>          (creates new app in src/app of your project)
'''

if __name__ == '__main__':
    if len(sys.argv) > 1:
        callback_name = sys.argv[1].replace('-', '_')
        try:
            callback = locals()[callback_name]
        except KeyError, e:
            _error('%r is not valid command.' % callback_name, None)
            _usage()
        else:
            callback(*sys.argv[2:])
    else:
        _usage()
