#!/usr/bin/python3
import argparse
from os import makedirs, listdir, rmdir, walk, rename, getcwd
from os.path import realpath, basename, isdir, join
from shutil import copytree, move


class AppConfig:
    def __init__(self, destination=None, package=None, name=None,
                 template=None):
        if destination:
            self.destination = destination
        else:
            self.destination = getcwd()

        if package:
            self.package = package
        else:
            self.package = 'com.company.product'

        if name:
            self.name = name
        else:
            # If KakavaApp/ exists create KakavaApp1/ and so on...
            default_name = 'KakavaApp'
            number = ''
            i = 1
            while isdir(join(self.destination, default_name + number)):
                number = str(i)
                i += 1

            self.name = default_name + number

        if template:
            self.template = template
        else:
            self.template = 'default'


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--destination',
                        help='output directory for the app')
    parser.add_argument('-p', '--package',
                        help='package name, e.g. com.example.app')
    parser.add_argument('-n', '--name', help='app name, e.g. MyApp')
    parser.add_argument('-t', '--template',
                        help='template directory name in the templates/ dir')
    args = parser.parse_args()
    return AppConfig(args.destination, args.package, args.name, args.template)


def create_package_structure(kakavaroot_path, package):
    # Get directories for creation from package
    dirs = package.split('.')
    dirs_to_create = dirs[0]
    for i in range(1, len(dirs)):
        dirs_to_create = join(dirs_to_create, dirs[i])

    # Create dir structure from package (com.example.app -> com/example/app)
    kakavaroot_index = kakavaroot_path.rfind('kakavaroot')
    kakavaroot_parent_path = kakavaroot_path[: kakavaroot_index]
    package_path = join(kakavaroot_parent_path, dirs_to_create)
    makedirs(package_path, exist_ok=True)

    # Move kakavaroot package into new structure (com/example/app/kakavaroot)
    move(kakavaroot_path, package_path)

    # Move kakavaroot/ content one level up and delete kakavaroot/
    kakavaroot_path = join(package_path, 'kakavaroot')
    for name in listdir(kakavaroot_path):
        move(join(package_path, 'kakavaroot', name), join(package_path, name))
    rmdir(kakavaroot_path)


def replace_word_in_file(name, word, replacement):
    with open(name, 'r', encoding='utf-8') as file_read:
        lines = ''.join(file_read.readlines())
        lines = lines.replace(word, replacement)
        with open(name, 'w', encoding='utf-8') as file_write:
            file_write.write(lines)


def replace_variables_in_file(name, app_cfg):
    replace_word_in_file(name, '${packageName}', app_cfg.package)
    replace_word_in_file(name, '${appName}', app_cfg.name)


if __name__ == '__main__':
    # Parse CL arguments
    app_config = parse_args()

    # Copy template folder to app_config.destination/app_config.name
    script_path = realpath(__file__)
    script_dir_path = script_path[: script_path.rfind(basename(__file__))]
    templates_dir_path = join(script_dir_path, 'templates')
    project_path = join(app_config.destination, app_config.name)
    default_template_path = join(templates_dir_path, app_config.template)
    copytree(default_template_path, project_path)

    # Create directories by splitting app_config.package
    # (kakavaroot/ -> com/example/app)
    for root, directories, filenames in walk(project_path):
        for directory in directories:
            dir_path = join(root, directory)
            if directory == 'kakavaroot' and isdir(dir_path):
                create_package_structure(dir_path, app_config.package)

    # Change ${...} variables in source files according to given options
    for root, directories, filenames in walk(project_path):
        for filename in filenames:
            if filename.endswith('.kakava'):
                file_path = join(root, filename)
                replace_variables_in_file(file_path, app_config)
                filename_without_postfix = filename[: filename.rfind('.kakava')]
                new_file_path = join(root, filename_without_postfix)
                rename(file_path, new_file_path)

    # Success message
    print(app_config.package, 'project successfully created in', project_path)
