import os, subprocess
import argparse
from pathlib import Path

from . import mlog
from .mesonlib import quiet_git, verbose_git, GitException, Popen_safe, MesonException, windows_proof_rmtree
from .wrap.wrap import API_ROOT, Resolver, WrapException, ALL_TYPES
from .wrap import wraptool

ALL_TYPES_STRING = ', '.join(ALL_TYPES)

def update_wrapdb_file(wrap):
    patch_url = wrap.get('patch_url')
    branch, revision = wraptool.parse_patch_url(patch_url)
    new_branch, new_revision = wraptool.get_latest_version(wrap.name)
    if new_branch != branch or new_revision != revision:
        wraptool.update_wrap_file(wrap.filename, wrap.name, new_branch, new_revision)
        mlog.log('  -> New wrap file downloaded.')

def update_file(r, wrap, repo_dir, options):
    patch_url = wrap.values.get('patch_url', '')
    if patch_url.startswith(API_ROOT):
        update_wrapdb_file(wrap)
    if not os.path.isdir(repo_dir):
        # The subproject is not needed, or it is a tarball extracted in
        # 'libfoo-1.0' directory and the version has been bumped and the new
        # directory is 'libfoo-2.0'. In that case forcing a meson
        # reconfigure will download and use the new tarball.
        mlog.log('  -> Not used.')
        return True
    elif options.reset:
        # Delete existing directory and redownload. It is possible that nothing
        # changed but we have no way to know. Hopefully tarballs are still
        # cached.
        windows_proof_rmtree(repo_dir)
        try:
            r.resolve(wrap.name, 'meson')
            mlog.log('  -> New version extracted')
            return True
        except WrapException as e:
            mlog.log('  ->', mlog.red(str(e)))
            return False
    else:
        # The subproject has not changed, or the new source and/or patch
        # tarballs should be extracted in the same directory than previous
        # version.
        mlog.log('  -> Subproject has not changed, or the new source/patch needs to be extracted on the same location.')
        mlog.log('     Pass --reset option to delete directory and redownload.')
        return False

def git_output(cmd, workingdir):
    return quiet_git(cmd, workingdir, check=True)[1]

def git_stash(workingdir):
    # That git command return 1 (failure) when there is something to stash.
    # We don't want to stash when there is nothing to stash because that would
    # print spurious "No local changes to save".
    if not quiet_git(['diff', '--quiet', 'HEAD'], workingdir)[0]:
        # Don't pipe stdout here because we want the user to see their changes have
        # been saved.
        verbose_git(['stash'], workingdir, check=True)

def git_show(repo_dir):
    commit_message = git_output(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]'], repo_dir)
    parts = [s.strip() for s in commit_message.split('\n')]
    mlog.log('  ->', mlog.yellow(parts[0]), mlog.red(parts[1]), parts[2], mlog.blue(parts[3]))

def git_rebase(repo_dir, revision):
    try:
        git_output(['-c', 'rebase.autoStash=true', 'rebase', 'FETCH_HEAD'], repo_dir)
    except GitException as e:
        mlog.log('  -> Could not rebase', mlog.bold(repo_dir), 'onto', mlog.bold(revision))
        mlog.log(mlog.red(e.output))
        mlog.log(mlog.red(str(e)))
        return False
    return True

def git_reset(repo_dir, revision):
    try:
        # Stash local changes, commits can always be found back in reflog, to
        # avoid any data lost by mistake.
        git_stash(repo_dir)
        git_output(['reset', '--hard', 'FETCH_HEAD'], repo_dir)
    except GitException as e:
        mlog.log('  -> Could not reset', mlog.bold(repo_dir), 'to', mlog.bold(revision))
        mlog.log(mlog.red(e.output))
        mlog.log(mlog.red(str(e)))
        return False
    return True

def git_checkout(repo_dir, revision, create=False):
    cmd = ['checkout', '--ignore-other-worktrees', revision, '--']
    if create:
        cmd.insert('-b', 1)
    try:
        # Stash local changes, commits can always be found back in reflog, to
        # avoid any data lost by mistake.
        git_stash(repo_dir)
        git_output(cmd, repo_dir)
    except GitException as e:
        mlog.log('  -> Could not checkout', mlog.bold(revision), 'in', mlog.bold(repo_dir))
        mlog.log(mlog.red(e.output))
        mlog.log(mlog.red(str(e)))
        return False
    return True

def git_checkout_and_reset(repo_dir, revision):
    # revision could be a branch that already exists but is outdated, so we still
    # have to reset after the checkout.
    success = git_checkout(repo_dir, revision)
    if success:
        success = git_reset(repo_dir, revision)
    return success

def git_checkout_and_rebase(repo_dir, revision):
    # revision could be a branch that already exists but is outdated, so we still
    # have to rebase after the checkout.
    success = git_checkout(repo_dir, revision)
    if success:
        success = git_rebase(repo_dir, revision)
    return success

def update_git(r, wrap, repo_dir, options):
    if not os.path.isdir(repo_dir):
        mlog.log('  -> Not used.')
        return True
    if not os.path.exists(os.path.join(repo_dir, '.git')):
        if options.reset:
            # Delete existing directory and redownload
            windows_proof_rmtree(repo_dir)
            try:
                r.resolve(wrap.name, 'meson')
                update_git_done(repo_dir)
                return True
            except WrapException as e:
                mlog.log('  ->', mlog.red(str(e)))
                return False
        else:
            mlog.log('  -> Not a git repository.')
            mlog.log('Pass --reset option to delete directory and redownload.')
            return False
    revision = wrap.values.get('revision')
    url = wrap.values.get('url')
    push_url = wrap.values.get('push-url')
    if not revision or not url:
        # It could be a detached git submodule for example.
        mlog.log('  -> No revision or URL specified.')
        return True
    try:
        origin_url = git_output(['remote', 'get-url', 'origin'], repo_dir).strip()
    except GitException as e:
        mlog.log('  -> Failed to determine current origin URL in', mlog.bold(repo_dir))
        mlog.log(mlog.red(e.output))
        mlog.log(mlog.red(str(e)))
        return False
    if options.reset:
        try:
            git_output(['remote', 'set-url', 'origin', url], repo_dir)
            if push_url:
                git_output(['remote', 'set-url', '--push', 'origin', push_url], repo_dir)
        except GitException as e:
            mlog.log('  -> Failed to reset origin URL in', mlog.bold(repo_dir))
            mlog.log(mlog.red(e.output))
            mlog.log(mlog.red(str(e)))
            return False
    elif url != origin_url:
        mlog.log(f'  -> URL changed from {origin_url!r} to {url!r}')
        return False
    try:
        # Same as `git branch --show-current` but compatible with older git version
        branch = git_output(['rev-parse', '--abbrev-ref', 'HEAD'], repo_dir).strip()
        branch = branch if branch != 'HEAD' else ''
    except GitException as e:
        mlog.log('  -> Failed to determine current branch in', mlog.bold(repo_dir))
        mlog.log(mlog.red(e.output))
        mlog.log(mlog.red(str(e)))
        return False
    try:
        # Fetch only the revision we need, this avoids fetching useless branches.
        # revision can be either a branch, tag or commit id. In all cases we want
        # FETCH_HEAD to be set to the desired commit and "git checkout <revision>"
        # to to either switch to existing/new branch, or detach to tag/commit.
        # It is more complicated than it first appear, see discussion there:
        # https://github.com/mesonbuild/meson/pull/7723#discussion_r488816189.
        heads_refmap = '+refs/heads/*:refs/remotes/origin/*'
        tags_refmap = '+refs/tags/*:refs/tags/*'
        git_output(['fetch', '--refmap', heads_refmap, '--refmap', tags_refmap, 'origin', revision], repo_dir)
    except GitException as e:
        mlog.log('  -> Could not fetch revision', mlog.bold(revision), 'in', mlog.bold(repo_dir))
        mlog.log(mlog.red(e.output))
        mlog.log(mlog.red(str(e)))
        return False

    if branch == '':
        # We are currently in detached mode
        if options.reset:
            success = git_checkout_and_reset(repo_dir, revision)
        else:
            success = git_checkout_and_rebase(repo_dir, revision)
    elif branch == revision:
        # We are in the same branch. A reset could still be needed in the case
        # a force push happened on remote repository.
        if options.reset:
            success = git_reset(repo_dir, revision)
        else:
            success = git_rebase(repo_dir, revision)
    else:
        # We are in another branch, either the user created their own branch and
        # we should rebase it, or revision changed in the wrap file and we need
        # to checkout the new branch.
        if options.reset:
            success = git_checkout_and_reset(repo_dir, revision)
        else:
            success = git_rebase(repo_dir, revision)
    if success:
        update_git_done(repo_dir)
    return success

def update_git_done(repo_dir):
    git_output(['submodule', 'update', '--checkout', '--recursive'], repo_dir)
    git_show(repo_dir)

def update_hg(r, wrap, repo_dir, options):
    if not os.path.isdir(repo_dir):
        mlog.log('  -> Not used.')
        return True
    revno = wrap.get('revision')
    if revno.lower() == 'tip':
        # Failure to do pull is not a fatal error,
        # because otherwise you can't develop without
        # a working net connection.
        subprocess.call(['hg', 'pull'], cwd=repo_dir)
    else:
        if subprocess.call(['hg', 'checkout', revno], cwd=repo_dir) != 0:
            subprocess.check_call(['hg', 'pull'], cwd=repo_dir)
            subprocess.check_call(['hg', 'checkout', revno], cwd=repo_dir)
    return True

def update_svn(r, wrap, repo_dir, options):
    if not os.path.isdir(repo_dir):
        mlog.log('  -> Not used.')
        return True
    revno = wrap.get('revision')
    p, out, _ = Popen_safe(['svn', 'info', '--show-item', 'revision', repo_dir])
    current_revno = out
    if current_revno == revno:
        return True
    if revno.lower() == 'head':
        # Failure to do pull is not a fatal error,
        # because otherwise you can't develop without
        # a working net connection.
        subprocess.call(['svn', 'update'], cwd=repo_dir)
    else:
        subprocess.check_call(['svn', 'update', '-r', revno], cwd=repo_dir)
    return True

def update(r, wrap, repo_dir, options):
    mlog.log(f'Updating {wrap.name}...')
    if wrap.type == 'file':
        return update_file(r, wrap, repo_dir, options)
    elif wrap.type == 'git':
        return update_git(r, wrap, repo_dir, options)
    elif wrap.type == 'hg':
        return update_hg(r, wrap, repo_dir, options)
    elif wrap.type == 'svn':
        return update_svn(r, wrap, repo_dir, options)
    elif wrap.type is None:
        mlog.log('  -> Cannot update subproject with no wrap file')
    else:
        mlog.log('  -> Cannot update', wrap.type, 'subproject')
    return True

def checkout(r, wrap, repo_dir, options):
    if wrap.type != 'git' or not os.path.isdir(repo_dir):
        return True
    branch_name = options.branch_name if options.branch_name else wrap.get('revision')
    if not branch_name:
        # It could be a detached git submodule for example.
        return True
    mlog.log(f'Checkout {branch_name} in {wrap.name}...')
    if git_checkout(repo_dir, branch_name, create=options.b):
        git_show(repo_dir)
        return True
    return False

def download(r, wrap, repo_dir, options):
    mlog.log(f'Download {wrap.name}...')
    if os.path.isdir(repo_dir):
        mlog.log('  -> Already downloaded')
        return True
    try:
        r.resolve(wrap.name, 'meson')
        mlog.log('  -> done')
    except WrapException as e:
        mlog.log('  ->', mlog.red(str(e)))
        return False
    return True

def foreach(r, wrap, repo_dir, options):
    mlog.log(f'Executing command in {repo_dir}')
    if not os.path.isdir(repo_dir):
        mlog.log('  -> Not downloaded yet')
        return True
    cmd = [options.command] + options.args
    p, out, _ = Popen_safe(cmd, stderr=subprocess.STDOUT, cwd=repo_dir)
    if p.returncode != 0:
        err_message = "Command '{}' returned non-zero exit status {}.".format(" ".join(cmd), p.returncode)
        mlog.log('  -> ', mlog.red(err_message))
        mlog.log(out, end='')
        return False

    mlog.log(out, end='')
    return True

def add_common_arguments(p):
    p.add_argument('--sourcedir', default='.',
                   help='Path to source directory')
    p.add_argument('--types', default='',
                   help=f'Comma-separated list of subproject types. Supported types are: {ALL_TYPES_STRING} (default: all)')

def add_subprojects_argument(p):
    p.add_argument('subprojects', nargs='*',
                   help='List of subprojects (default: all)')

def add_arguments(parser):
    subparsers = parser.add_subparsers(title='Commands', dest='command')
    subparsers.required = True

    p = subparsers.add_parser('update', help='Update all subprojects from wrap files')
    p.add_argument('--rebase', default=True, action='store_true',
                   help='Rebase your branch on top of wrap\'s revision. ' + \
                        'Deprecated, it is now the default behaviour. (git only)')
    p.add_argument('--reset', default=False, action='store_true',
                   help='Checkout wrap\'s revision and hard reset to that commit. (git only)')
    add_common_arguments(p)
    add_subprojects_argument(p)
    p.set_defaults(subprojects_func=update)

    p = subparsers.add_parser('checkout', help='Checkout a branch (git only)')
    p.add_argument('-b', default=False, action='store_true',
                   help='Create a new branch')
    p.add_argument('branch_name', nargs='?',
                   help='Name of the branch to checkout or create (default: revision set in wrap file)')
    add_common_arguments(p)
    add_subprojects_argument(p)
    p.set_defaults(subprojects_func=checkout)

    p = subparsers.add_parser('download', help='Ensure subprojects are fetched, even if not in use. ' +
                                               'Already downloaded subprojects are not modified. ' +
                                               'This can be used to pre-fetch all subprojects and avoid downloads during configure.')
    add_common_arguments(p)
    add_subprojects_argument(p)
    p.set_defaults(subprojects_func=download)

    p = subparsers.add_parser('foreach', help='Execute a command in each subproject directory.')
    p.add_argument('command', metavar='command ...',
                   help='Command to execute in each subproject directory')
    p.add_argument('args', nargs=argparse.REMAINDER,
                   help=argparse.SUPPRESS)
    add_common_arguments(p)
    p.set_defaults(subprojects=[])
    p.set_defaults(subprojects_func=foreach)

def run(options):
    src_dir = os.path.relpath(os.path.realpath(options.sourcedir))
    if not os.path.isfile(os.path.join(src_dir, 'meson.build')):
        mlog.error('Directory', mlog.bold(src_dir), 'does not seem to be a Meson source directory.')
        return 1
    subprojects_dir = os.path.join(src_dir, 'subprojects')
    if not os.path.isdir(subprojects_dir):
        mlog.log('Directory', mlog.bold(src_dir), 'does not seem to have subprojects.')
        return 0
    r = Resolver(src_dir, 'subprojects')
    if options.subprojects:
        wraps = [wrap for name, wrap in r.wraps.items() if name in options.subprojects]
    else:
        wraps = r.wraps.values()
    types = [t.strip() for t in options.types.split(',')] if options.types else []
    for t in types:
        if t not in ALL_TYPES:
            raise MesonException(f'Unknown subproject type {t!r}, supported types are: {ALL_TYPES_STRING}')
    failures = []
    for wrap in wraps:
        if types and wrap.type not in types:
            continue
        dirname = Path(subprojects_dir, wrap.directory).as_posix()
        if not options.subprojects_func(r, wrap, dirname, options):
            failures.append(wrap.name)
    if failures:
        m = 'Please check logs above as command failed in some subprojects which could have been left in conflict state: '
        m += ', '.join(failures)
        mlog.warning(m)
    return len(failures)
