#!/usr/local/opt/python@2/bin/python2.7
# -*- coding: utf-8 -*-
from os import path, system, getcwd, remove
from click import group, option, argument, CommandCollection
from generator import *
from urllib import urlretrieve
import re

__author__ = "Loi Nguyen <loinguyentrung@gmail.com>"


def require_composer():
    if not path.isfile('./composer.json'):
        print('Error ! composer.json is missing.')
        exit(1)
    from distutils.spawn import find_executable
    if find_executable('composer') is None:
        print('Error ! Composer is require for PHP Project')
    if not path.isdir(getcwd() + '/vendor'):
        system('composer install --prefer-dist --no-interaction')


def require_bootstrap():
    if not path.isfile('./src/Bootstrap.php'):
        print('Error ! src/Bootstrap.php is missing')
        exit(1)


def require_artisan():
    if not path.isfile('./artisan'):
        print('Error ! Missing Laravel artisan')
        exit(1)


@group()
def create_cli():
    pass


@create_cli.command()
@option('--quite', is_flag=True, default=False)
@option('--force', is_flag=True, default=False)
@option('--mysql', is_flag=True, default=False)
@argument('name')
def create(name, quite, force, mysql):
    name_pattern = re.compile("^[a-z-]+$")
    if not name_pattern.match(name):
        print('Sorry ! Only lower case and hyphen are allowed . Please try again')
        exit(1)
    """ If your machine does not have MySQL then it will up for you """
    if mysql:
        print('Preparing MySQL ...')
        system('docker rm -f mysql || true')
        system('docker run -d -p 3306:3306 --name=mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=database mysql:5.6')

    """Create micro service application"""
    if not force and path.isdir(name):
        print('Directory ', name, ' does not empty !')
        confirm_override = raw_input('Would you like to override it ? y/n : ')
        if confirm_override.lower() != 'y':
            exit(0)

    # Default is empty
    host = username = password = database = ''

    if not quite and not mysql:
        host = raw_input('Enter mysql host [127.0.0.1] :')
        username = raw_input('Enter mysql user [root] :')
        password = raw_input('Enter mysql password [password] : ')
        database = raw_input('Enter mysql database [database] : ')

    # Fill default value if user ignore them
    if len(host) == 0:
        host = '127.0.0.1'
    if len(username) == 0:
        username = 'root'
    if len(password) == 0:
        password = 'password'
    if len(database) == 0:
        database = 'database'

    # Generate rest.json
    rest_content = REST_TEMPLATE
    rest_content = rest_content.replace('{app_name}', name)
    rest_content = rest_content.replace('{host}', host)
    rest_content = rest_content.replace('{username}', username)
    rest_content = rest_content.replace('{password}', password)
    rest_content = rest_content.replace('{database}', database)

    # Generate config/database.php
    database_content = DATABASE_TEMPLATE
    database_content = database_content.replace('{host}', host)
    database_content = database_content.replace('{username}', username)
    database_content = database_content.replace('{password}', password)
    database_content = database_content.replace('{database}', database)

    try:
        system('rm -rf user')
        system('rm -f app.zip')
        system('rm -rf rest-skeleton-master')
        urlretrieve('https://github.com/loint/rest-skeleton/archive/master.zip', 'app.zip')
        system('unzip app.zip')
        system('rm -f app.zip')
        system('mv rest-skeleton-master ' + name)
        rest_file = open(name + '/rest.json', 'w')
        rest_file.write(rest_content)
        rest_file.close()
        database_file = open(name + '/config/database.php', 'w')
        database_file.write(database_content)
        database_file.close()
    except IOError:
        print('Can not create application !')
        raise


@group()
def migrate_cli():
    pass


@migrate_cli.command()
def migrate():
    """Migrate database schema"""
    require_composer()
    require_bootstrap()
    require_artisan()
    print('Start migration')
    if not path.isdir('./src/Shared/Migration'):
        print('Please put your migration in src/Shared/Migration')
        exit(1)
    system('php artisan migrate:refresh --path=src/Shared/Migration --force')


def sync_schemas():
    print('Synchronizing schema ...')
    generator = ModelGenerator()
    generator.set_identifier('// AUTO GENERATED - DO NOT MODIFY FROM HERE')
    generator.config_paths()
    # Overview scan and detect new schema
    generator.scan_models()
    generator.scan_database()
    generator.generate_models()
    # Scan annotated query
    generator.scan_models()
    generator.scan_model_annotation()
    generator.generate_repositories()
    # Full scan and fill missing parts
    generator.scan_models()
    generator.scan_database()
    generator.generate_models()


def sync_routes_docs():
    system('php route.php')


@group()
def sync_cli():
    pass


@sync_cli.command()
def sync():
    """
    Synchronize schema and api routes
    """
    sync_schemas()
    sync_routes_docs()
    # Verify result after synchronize
    route()
    test()


@group()
def route_cli():
    pass


@route_cli.command()
def route():
    """
    Synchronize schema and api route
    """
    system('php artisan route:list')


@group()
def serve_cli():
    pass


@serve_cli.command()
def serve():
    """Serve application with PHP built-in server"""
    require_composer()
    system('php -S localhost:8000 -t public')


@group()
def test_cli():
    pass


@test_cli.command()
def test():
    """Run test cases with PHPUnit"""
    require_composer()
    require_bootstrap()
    log_file = 'storage/logs/lumen.log'
    if path.isdir(log_file):
        remove(log_file)
    system('php ./vendor/phpunit/phpunit/phpunit --bootstrap src/Bootstrap.php -c phpunit.xml --testdox')
    if path.isfile(log_file):
        with open(log_file, 'r') as log_content:
            print log_content.read()


@group()
def version_cli():
    pass


@version_cli.command()
def version():
    """Check current version"""
    print('Coming soon !')


@group()
def upgrade_cli():
    pass


@upgrade_cli.command()
def upgrade():
    """Upgrade rest command to latest version"""
    print('Coming soon !')


cli = CommandCollection(sources=[
    create_cli,
    migrate_cli,
    sync_cli,
    route_cli,
    serve_cli,
    test_cli,
    version_cli,
    upgrade_cli
])

if __name__ == '__main__':
    cli()
