#!/usr/bin/env python3

# Copyright 2017 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import ruamel.yaml


def get_single_key(var):
    if isinstance(var, str):
        return var
    elif isinstance(var, list):
        return var[0]
    return list(var.keys())[0]


def get_comment_text(token):
    if token is None:
        return ''
    elif isinstance(token, list):
        text = ''
        for subtoken in token:
            if subtoken:
                text += get_comment_text(subtoken)
        return text
    else:
        return token.value


def add_projects():
    yaml = ruamel.yaml.YAML()
    yaml.indent(mapping=2, sequence=4, offset=2)
    all_projects = yaml.load(open('gerrit/projects.yaml', 'r'))
    zuul_main = yaml.load(open('zuul/main.yaml', 'r'))

    existing_projects = set()
    gerrit = None
    for tenant in zuul_main:
        if tenant['tenant']['name'] == 'openstack':
            gerrit = tenant['tenant']['source']['gerrit']
            break

    # Find the point in the list where we want to add things and save the
    # comment text from it so that we can re-add it
    sorted_index = None
    saved_comment = None
    for idx, token in gerrit['untrusted-projects'].ca.items.items():
        text = get_comment_text(token)
        if text.startswith('# After this point'):
            sorted_index = idx
            saved_comment = token
            break

    # Get the list of things above the marker comment
    for project_type in ('config-projects', 'untrusted-projects'):
        for idx, project in enumerate(gerrit[project_type]):
            if idx == sorted_index:
                break
            if isinstance(project, dict):
                project = get_single_key(project)
            existing_projects.add(project)

    new_projects = []
    for project in all_projects:
        name = project['project']
        # It's in the file, already - it's taken care of
        if name in existing_projects:
            continue

        # Skip or remove retired projects
        is_retired = name.split('/')[0].endswith('-attic')
        in_attic = project.get('acl-config', '').endswith('/retired.config')
        if is_retired or in_attic:
            if name in gerrit['untrusted-projects']:
                del gerrit['untrusted-projects'][name]
            continue

        new_projects.append(name)

    # Pop things off the end of the list until we're down at the length
    # indicated by the saved index position. We have to do this weirdly
    # with passing the index to pop because it's not a real list
    for idx in reversed(range(sorted_index,
                              len(gerrit['untrusted-projects']))):
        gerrit['untrusted-projects'].pop(idx)

    # Toss in a sorted just to make sure - the source list should be sorted
    # but why tempt fate right?
    gerrit['untrusted-projects'].extend(sorted(new_projects))
    gerrit['untrusted-projects'].ca.items[sorted_index] = saved_comment

    yaml.dump(zuul_main, open('zuul/main.yaml', 'w'))

    # Strip the extra 2 spaces that ruamel.yaml appends because we told it
    # to indent an extra 2 spaces. Because the top level entry is a list it
    # applies that indentation at the top. It doesn't indent the comment lines
    # extra though, so don't do them.
    with open('zuul/main.yaml', 'r') as main_in:
        main_content = main_in.readlines()
    with open('zuul/main.yaml', 'w') as main_out:
        for line in main_content:
            if '#' in line:
                main_out.write(line)
            else:
                main_out.write(line[2:])


def main():
    add_projects()


if __name__ == '__main__':
    main()