#!/usr/bin/env python
#pylint: disable-msg=W0612

import readline
import argparse
import yaml
import os
import sys


 
from . import MongoDb
from . import Mysql
from . import Postgre
from . import Redis

from . import Angular

from . import RabbitMq

from . import IdentityServer4

from . import DotnetApi
from . import NodeApi

from . import Nginx
from . import Docker

parser = argparse.ArgumentParser(description='Generate and start your new project from moon')
parser.add_argument('--config','-c', type=str, help='Configuration file', required=True)
parser.add_argument('--output','-o', type=str, help='Output directory', required=False)
parser.add_argument('--force','-f',type=bool)

args = vars(parser.parse_args())
configFilePath = os.path.join(os.getcwd(),args['config'])
projectOptions = {}

scriptPath = os.path.dirname(os.path.realpath(sys.argv[0]))
templatesPath = os.path.normpath(os.path.join(scriptPath,'templatefiles'))




def CreateProjectDirectory(projectName):

    project_output_dir = None
    if args['output'] is not None :
        project_output_dir = os.path.normpath(os.path.join(os.getcwd(),args['output']))
    else:
        project_output_dir = os.path.normpath(os.path.join(os.getcwd(),projectName))

    srcDir = os.path.normpath(os.path.join(project_output_dir,"src"))
    docker_volume_dir = os.path.normpath(os.path.join(project_output_dir,"docker_volumes"))
    if not os.path.isdir(srcDir):
        os.makedirs(srcDir)
    if not os.path.isdir(docker_volume_dir):
        os.makedirs(docker_volume_dir)
    # Create README.md
    f = open(os.path.normpath(os.path.join(project_output_dir,'README.md')), 'w+')
    f.write('#'+projectName)
    f.close()
    return project_output_dir, srcDir
    

def HandleServers(servers):
    print ('Configuring Servers')
    for server in servers:
        server_options = list(server.values())[0]
        print('Building'+ server_options['name'])
        if server_options['type'] == 'nginx':
            nginx_instance = Nginx(projectOptions,templatesPath,project_output_dir, server_options)
            nginx_instance.GenerateNginxInstance()


def HandleDatabases(databases):
    print ('Configuring Databases')
    for db in databases:
        db_options = list(db.values())[0]
        print('Scaffolding '+db_options['name'])
        if(db_options['type'] == 'postgresql'):
            postgre_ins = Postgre(projectOptions,templatesPath,project_output_dir)
            postgre_ins.HandlePostgre(db_options)
        if(db_options['type'] == 'mysql'):
            mysql_ins = Mysql(projectOptions,templatesPath,project_output_dir)
            mysql_ins.HandleMysql(db_options)
        elif db_options['type'] == 'redis':
            redis_ins = Redis(projectOptions,templatesPath,project_output_dir)
            redis_ins.HandleRedisDatabase(db_options)
        elif db_options['type'] == 'mongodb':
            mongo_ins = MongoDb(projectOptions,templatesPath,project_output_dir)
            mongo_ins.HandleMongoDb(db_options)


def HandleEventBus(eventbuses):
    print ('Configuring Bus Instances..')
    for evenbus in eventbuses:
        evenbus_options = list(evenbus.values())[0]
        print('Scaffolding '+evenbus_options['name'])
        if(evenbus_options['type'] == 'rabbitmq'):
            rabbit_ins = RabbitMq(projectOptions,templatesPath,project_output_dir)
            rabbit_ins.HandleRabbitMq(evenbus_options)

def HandleIdentityServices(identity_services):
    print ('Scaffolding Identity Services...')
    for i_service in identity_services:
        i_service_options = list(i_service.values())[0]
        if (i_service_options['type']=='identityserver4'):
            is4_ins = IdentityServer4(projectOptions,templatesPath,project_output_dir)
            is4_ins.HandleIdentityServer4(i_service_options)


def HandleApiServices(api_services):
    print ('Scaffolding Api Services')
    for api_service in api_services:
        api_service_options = list(api_service.values())[0]
        if(api_service_options['type']=='dotnet_web_api'):
            dotnetapi_ins = DotnetApi(projectOptions,templatesPath,project_output_dir)
            dotnetapi_ins.HandleDotnetApiService(api_service_options)
        if(api_service_options['type']=='node_web_api'):
            nodeapi_ins = NodeApi(projectOptions,templatesPath,project_output_dir)
            nodeapi_ins.HandleNodeWebApi(api_service_options)



def HandleClients(clients):
    print ('Scaffolding Clients')
    for client in clients:
        client_options = list(client.values())[0]
        if(client_options['type']=='angular_cli_6_ssr'):
            angular_ins = Angular(projectOptions,templatesPath,project_output_dir)
            angular_ins.HandleAngular6SsrClient(client_options) 



with open(configFilePath, 'r') as stream:
    try:
        # Load Yaml
        projectOptions = yaml.load(stream)
        if not ('name' in projectOptions):
            print('Please Provide a valid project name')
            exit
        projectName = projectOptions['name']
        # Create Project Files
        project_output_dir, srcDir = CreateProjectDirectory(projectName)
        # init as singleton
        dock = Docker(projectOptions,templatesPath,project_output_dir)

        # Create Servers (Nginx Apache)
        if('servers' in projectOptions):
            HandleServers(projectOptions['servers'])

        # Create Databases (Postgre, Mysql, Redis)
        if('databases' in projectOptions):
            HandleDatabases(projectOptions['databases'])
            
        # Configure Eventbus Instances (Rabbitmq)
        if('eventbus' in projectOptions):
            HandleEventBus(projectOptions['eventbus'])

        # Create and configure identity_services
        if('identity_services' in projectOptions):
            HandleIdentityServices(projectOptions['identity_services'])

        # Create and configure api_serviecs
        if('api_services' in projectOptions):
            HandleApiServices(projectOptions['api_services'])
        # Create and configure clients
        if('clients' in projectOptions):
            HandleClients(projectOptions['clients'])

        docker_compose_path = os.path.join(project_output_dir,'docker-compose.yml')
        dock.DumpTo(docker_compose_path)
        dock.DockerComposeFinalization(docker_compose_path)

        
    except yaml.YAMLError as exc:
        print('Error parsing yml document')
        print(exc)    

