#
# Helper functions for committing data to git and pushing upstream
#
# Copyright (c) 2017, Intel Corporation.
# Copyright (c) 2019, Linux Foundation
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#

import os
import re
import sys
from operator import attrgetter
from collections import namedtuple
from oeqa.utils.git import GitRepo, GitError

class ArchiveError(Exception):
    """Internal error handling of this script"""

def format_str(string, fields):
    """Format string using the given fields (dict)"""
    try:
        return string.format(**fields)
    except KeyError as err:
        raise ArchiveError("Unable to expand string '{}': unknown field {} "
                           "(valid fields are: {})".format(
                               string, err, ', '.join(sorted(fields.keys()))))


def init_git_repo(path, no_create, bare, log):
    """Initialize local Git repository"""
    path = os.path.abspath(path)
    if os.path.isfile(path):
        raise ArchiveError("Invalid Git repo at {}: path exists but is not a "
                           "directory".format(path))
    if not os.path.isdir(path) or not os.listdir(path):
        if no_create:
            raise ArchiveError("No git repo at {}, refusing to create "
                               "one".format(path))
        if not os.path.isdir(path):
            try:
                os.mkdir(path)
            except (FileNotFoundError, PermissionError) as err:
                raise ArchiveError("Failed to mkdir {}: {}".format(path, err))
        if not os.listdir(path):
            log.info("Initializing a new Git repo at %s", path)
            repo = GitRepo.init(path, bare)
    try:
        repo = GitRepo(path, is_topdir=True)
    except GitError:
        raise ArchiveError("Non-empty directory that is not a Git repository "
                           "at {}\nPlease specify an existing Git repository, "
                           "an empty directory or a non-existing directory "
                           "path.".format(path))
    return repo


def git_commit_data(repo, data_dir, branch, message, exclude, notes, log):
    """Commit data into a Git repository"""
    log.info("Committing data into to branch %s", branch)
    tmp_index = os.path.join(repo.git_dir, 'index.oe-git-archive')
    try:
        # Create new tree object from the data
        env_update = {'GIT_INDEX_FILE': tmp_index,
                      'GIT_WORK_TREE': os.path.abspath(data_dir)}
        repo.run_cmd('add .', env_update)

        # Remove files that are excluded
        if exclude:
            repo.run_cmd(['rm', '--cached'] + [f for f in exclude], env_update)

        tree = repo.run_cmd('write-tree', env_update)

        # Create new commit object from the tree
        parent = repo.rev_parse(branch)
        git_cmd = ['commit-tree', tree, '-m', message]
        if parent:
            git_cmd += ['-p', parent]
        commit = repo.run_cmd(git_cmd, env_update)

        # Create git notes
        for ref, filename in notes:
            ref = ref.format(branch_name=branch)
            repo.run_cmd(['notes', '--ref', ref, 'add',
                          '-F', os.path.abspath(filename), commit])

        # Update branch head
        git_cmd = ['update-ref', 'refs/heads/' + branch, commit]
        if parent:
            git_cmd.append(parent)
        repo.run_cmd(git_cmd)

        # Update current HEAD, if we're on branch 'branch'
        if not repo.bare and repo.get_current_branch() == branch:
            log.info("Updating %s HEAD to latest commit", repo.top_dir)
            repo.run_cmd('reset --hard')

        return commit
    finally:
        if os.path.exists(tmp_index):
            os.unlink(tmp_index)


def expand_tag_strings(repo, name_pattern, msg_subj_pattern, msg_body_pattern,
                       keywords):
    """Generate tag name and message, with support for running id number"""
    keyws = keywords.copy()
    # Tag number is handled specially: if not defined, we autoincrement it
    if 'tag_number' not in keyws:
        # Fill in all other fields than 'tag_number'
        keyws['tag_number'] = '{tag_number}'
        tag_re = format_str(name_pattern, keyws)
        # Replace parentheses for proper regex matching
        tag_re = tag_re.replace('(', '\(').replace(')', '\)') + '$'
        # Inject regex group pattern for 'tag_number'
        tag_re = tag_re.format(tag_number='(?P<tag_number>[0-9]{1,5})')

        keyws['tag_number'] = 0
        for existing_tag in repo.run_cmd('tag').splitlines():
            match = re.match(tag_re, existing_tag)

            if match and int(match.group('tag_number')) >= keyws['tag_number']:
                keyws['tag_number'] = int(match.group('tag_number')) + 1

    tag_name = format_str(name_pattern, keyws)
    msg_subj= format_str(msg_subj_pattern.strip(), keyws)
    msg_body = format_str(msg_body_pattern, keyws)
    return tag_name, msg_subj + '\n\n' + msg_body

def gitarchive(data_dir, git_dir, no_create, bare, commit_msg_subject, commit_msg_body, branch_name, no_tag, tagname, tag_msg_subject, tag_msg_body, exclude, notes, push, keywords, log):

    if not os.path.isdir(data_dir):
        raise ArchiveError("Not a directory: {}".format(data_dir))

    data_repo = init_git_repo(git_dir, no_create, bare, log)

    # Expand strings early in order to avoid getting into inconsistent
    # state (e.g. no tag even if data was committed)
    commit_msg = format_str(commit_msg_subject.strip(), keywords)
    commit_msg += '\n\n' + format_str(commit_msg_body, keywords)
    branch_name = format_str(branch_name, keywords)
    tag_name = None
    if not no_tag and tagname:
        tag_name, tag_msg = expand_tag_strings(data_repo, tagname,
                                               tag_msg_subject,
                                               tag_msg_body, keywords)

    # Commit data
    commit = git_commit_data(data_repo, data_dir, branch_name,
                             commit_msg, exclude, notes, log)

    # Create tag
    if tag_name:
        log.info("Creating tag %s", tag_name)
        data_repo.run_cmd(['tag', '-a', '-m', tag_msg, tag_name, commit])

    # Push data to remote
    if push:
        cmd = ['push', '--tags']
        # If no remote is given we push with the default settings from
        # gitconfig
        if push is not True:
            notes_refs = ['refs/notes/' + ref.format(branch_name=branch_name)
                           for ref, _ in notes]
            cmd.extend([push, branch_name] + notes_refs)
        log.info("Pushing data to remote")
        data_repo.run_cmd(cmd)

# Container class for tester revisions
TestedRev = namedtuple('TestedRev', 'commit commit_number tags')

def get_test_runs(log, repo, tag_name, **kwargs):
    """Get a sorted list of test runs, matching given pattern"""
    # First, get field names from the tag name pattern
    field_names = [m.group(1) for m in re.finditer(r'{(\w+)}', tag_name)]
    undef_fields = [f for f in field_names if f not in kwargs.keys()]

    # Fields for formatting tag name pattern
    str_fields = dict([(f, '*') for f in field_names])
    str_fields.update(kwargs)

    # Get a list of all matching tags
    tag_pattern = tag_name.format(**str_fields)
    tags = repo.run_cmd(['tag', '-l', tag_pattern]).splitlines()
    log.debug("Found %d tags matching pattern '%s'", len(tags), tag_pattern)

    # Parse undefined fields from tag names
    str_fields = dict([(f, r'(?P<{}>[\w\-.()]+)'.format(f)) for f in field_names])
    str_fields['branch'] = r'(?P<branch>[\w\-.()/]+)'
    str_fields['commit'] = '(?P<commit>[0-9a-f]{7,40})'
    str_fields['commit_number'] = '(?P<commit_number>[0-9]{1,7})'
    str_fields['tag_number'] = '(?P<tag_number>[0-9]{1,5})'
    # escape parenthesis in fields in order to not messa up the regexp
    fixed_fields = dict([(k, v.replace('(', r'\(').replace(')', r'\)')) for k, v in kwargs.items()])
    str_fields.update(fixed_fields)
    tag_re = re.compile(tag_name.format(**str_fields))

    # Parse fields from tags
    revs = []
    for tag in tags:
        m = tag_re.match(tag)
        groups = m.groupdict()
        revs.append([groups[f] for f in undef_fields] + [tag])

    # Return field names and a sorted list of revs
    return undef_fields, sorted(revs)

def get_test_revs(log, repo, tag_name, **kwargs):
    """Get list of all tested revisions"""
    fields, runs = get_test_runs(log, repo, tag_name, **kwargs)

    revs = {}
    commit_i = fields.index('commit')
    commit_num_i = fields.index('commit_number')
    for run in runs:
        commit = run[commit_i]
        commit_num = run[commit_num_i]
        tag = run[-1]
        if not commit in revs:
            revs[commit] = TestedRev(commit, commit_num, [tag])
        else:
            assert commit_num == revs[commit].commit_number, "Commit numbers do not match"
            revs[commit].tags.append(tag)

    # Return in sorted table
    revs = sorted(revs.values(), key=attrgetter('commit_number'))
    log.debug("Found %d tested revisions:\n    %s", len(revs),
              "\n    ".join(['{} ({})'.format(rev.commit_number, rev.commit) for rev in revs]))
    return revs

def rev_find(revs, attr, val):
    """Search from a list of TestedRev"""
    for i, rev in enumerate(revs):
        if getattr(rev, attr) == val:
            return i
    raise ValueError("Unable to find '{}' value '{}'".format(attr, val))

