import click
import shutil
import yaml
from dulwich.repo import Repo
from pathlib import Path
from dulwich.errors import NotGitRepository
from configparser import ConfigParser
from matador import git


def deployment_repository(project_folder):
    project = Path(project_folder).name
    deployment_folder = Path(Path.home(), '.matador', project)
    deployment_repo_folder = Path(deployment_folder, 'repository')

    Path.mkdir(deployment_folder, parents=True, exist_ok=True)
    Path.mkdir(deployment_repo_folder, parents=True, exist_ok=True)

    try:
        repo = Repo(str(deployment_repo_folder))
    except NotGitRepository:
        config_file = Path(deployment_repo_folder, '.git', 'config')
        config = ConfigParser()

        repo = Repo.init(str(deployment_repo_folder))
        config.read(str(config_file))

        config['core']['sparsecheckout'] = 'true'
        config['remote "origin"'] = {
            'url': project_folder.as_posix(),
            'fetch': '+refs/heads/*:refs/remotes/origin/*'
        }

        with config_file.open('w') as f:
            config.write(f)

        sparse_checkout_file = Path(
            deployment_repo_folder, '.git', 'info', 'sparse-checkout')
        with sparse_checkout_file.open('a') as f:
            f.write('/src\n')
            f.write('/deploy\n')

    return repo


def ticket_deployment_folder(environment, ticket, commit, packaged):
    project_repo = Repo.discover()
    project_folder = Path(project_repo.path)
    project = project_folder.name
    ticket_deployment_folder = Path(
        Path.home(), '.matador', project, environment, 'tickets', ticket)
    if commit is None:
        commit = project_repo.head().decode(encoding='ascii')
    deployment_repo = deployment_repository(project_folder)
    ticket_src_folder = Path(deployment_repo.path, 'deploy', 'tickets', ticket)
    if not packaged:
        git.fetch_all(project_repo, deployment_repo)

    shutil.rmtree(str(ticket_deployment_folder), ignore_errors=True)
    git.checkout(deployment_repo, commit)
    shutil.copytree(str(ticket_src_folder), str(ticket_deployment_folder))
    return ticket_deployment_folder


def package_definition(environment, package, commit):
    project_repo = Repo.discover()
    project_folder = Path(project_repo.path)
    project = project_folder.name
    package_deployment_folder = Path(
        Path.home(), '.matador', project, environment, 'packages', package)
    deployment_repo = deployment_repository(project_folder)
    package_src_folder = Path(
        deployment_repo.path, 'deploy', 'packages', package)

    git.fetch_all(project_repo, deployment_repo)
    shutil.rmtree(str(package_deployment_folder), ignore_errors=True)
    git.checkout(deployment_repo, commit)
    shutil.copytree(str(package_src_folder), str(package_deployment_folder))
    tickets_file = Path(package_deployment_folder, 'tickets.yml')
    return tickets_file


def environments():
    project_folder = Path(Repo.discover().path)
    file_path = Path(
        project_folder, 'config', 'environments.yml')
    try:
        file = file_path.open('r')
        environments = yaml.load(file)
        if environments:
            return environments
        else:
            raise ValueError()
    except FileNotFoundError:
        click.echo('Cannot find environments.yml file')
    except ValueError:
        click.echo('environments.yml exists but is empty')


def credentials():
    project_folder = Path(Repo.discover().path)
    file_path = Path(
        project_folder, 'config', 'credentials.yml')
    try:
        file = file_path.open('r')
        credentials = yaml.load(file)
        if credentials:
            return credentials
        else:
            raise ValueError()
    except FileNotFoundError:
        click.echo('Cannot find credentials.yml file')
    except ValueError:
        click.echo('credentials.yml exists but is empty')
