#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#
# Copyright (C) 2017 Samsung Electronics.Co.Ltd.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; version 2
#    of the License.
#
#    This program is distributed in the hope that 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.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
"""This script will pull latest change to local when remote ref updated..
"""

import os
import sys
import time
import copy
import shutil
import ast
import re
import yaml
from six import iteritems
import collections
from collections import OrderedDict
from datetime import datetime

from common.git import Git, clone_gitproject
from common.gerrit import get_gerrit_event
from gbp.git.repository import GitRepositoryError

from common.mapping import git_obs_map

class LocalError(Exception):
    """Local error exception."""
    pass

# YAML PARSER WRAPPERS
class MyDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(MyDumper, self).increase_indent(flow, False)
_mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
def dict_representer(dumper, data):
    return dumper.represent_dict(iteritems(data))
def dict_constructor(loader, node):
    return collections.OrderedDict(loader.construct_pairs(node))
yaml.add_representer(collections.OrderedDict, dict_representer)
yaml.add_constructor(_mapping_tag, dict_constructor)

SNAPSHOT_TEMPLATE = """
Name: %s
Link: %s 
Release: "%s"
TopLevel: %s
Project: %s
ProjectConfig: %s
%s
%s
Targets: %s
"""

def checkout_new_branch(package, new_branch, branch_from=None):

    _ws = os.path.join(os.getenv('WORKSPACE'), \
                       os.path.basename(package))

    # Directly clone from remote without cache directory.
    clone_gitproject(package, _ws)
    mygit = Git(_ws)
    mygit.fetch(tags=True, all_remotes=True)
    if not mygit.has_branch('origin/' + new_branch, remote = True):
        mygit.create_branch(new_branch, rev=branch_from)
        print 'New branch [%s] created from [%s]' % (new_branch, branch_from)
    mygit.checkout(new_branch)

    return mygit

def push_local_changes(git_inst, target_branch, comment):
    try:
        git_inst.add_files('*', True)
        git_inst.commit_staged('Auto generated: %s' % (comment))
        git_inst.push(repo = 'origin', src = '%s' % target_branch)
    except GitRepositoryError as err:
        raise LocalError('Git push failed. No local changes?')

def convert_arch_name(arch):
    ARCH_MAP = {'i686': 'ia32',
                'i586': 'ia32'}
    for A in ARCH_MAP:
        if arch == A: return ARCH_MAP[arch]

    return arch

def configure_snapshot_repo_conf(project, repo_arch_map, enable_snapshot=True, enable_prerelease=False, conf_dir='default', snapshot_dir=None):
    conf_name = project.replace(':', '-').capitalize()
    link = 'latest'
    release_name = conf_name.lower()
    toplevel = '/srv/builds/temp/%s' % release_name
    projectconfig = 'yes'
    if snapshot_dir is not None:
        snapshotdir = snapshot_dir
    else:
        snapshotdir = 'snapshots/%s/%s' % (release_name.split('-')[0], '-'.join(release_name.split('-')[1:]))
    prereleasedir = snapshotdir.replace('snapshots', 'prerelease')
    if enable_snapshot:
        snapshotdir = 'SnapshotDir: %s' % snapshotdir
    else:
        snapshotdir = '#SnapshotDir: %s' % snapshotdir
    if enable_prerelease:
        prereleasedir = 'PrereleaseDir: %s' % prereleasedir
    else:
        prereleasedir = '#PrereleaseDir: %s' % prereleasedir
    # Repo arch map
    repo_arch = ''
    for repo in repo_arch_map:
        repo_arch += '\n  - Name: %s\n    Architectures:' % repo
        for arch in repo_arch_map[repo]:
            repo_arch += '\n      - %s' % convert_arch_name(arch)

    template = SNAPSHOT_TEMPLATE % (conf_name, link, release_name, toplevel, project, projectconfig, snapshotdir, prereleasedir, repo_arch)
    print 'TEMPLATE\n===='
    print template
    print '===='

    # Push changes to git
    package = os.getenv('REPOSYAML_PRJ')
    target_branch = 'master'
    mygit = checkout_new_branch(package, \
                                target_branch, branch_from='origin/master')
    working_dir = os.path.basename(package)

    conf_file_name = ''
    if conf_dir is not None and conf_dir != '':
        conf_file_dir = os.path.join(working_dir, conf_dir)
        conf_file_name = os.path.join(conf_file_dir, '%s.yaml' % conf_name)
        try:
            os.mkdir(conf_file_dir)
        except Exception as err:
            print repr(err)
    else:
        #TODO: Do not update repos.yaml
        assert False

    #TODO: Remove previous contents if its not the same file...
    for root, dirs, files in os.walk(working_dir):
        for x in files:
            if os.path.join(root, x) == conf_file_name:
                continue
            if x.endswith('%s.yaml' % conf_name):
                print 'You already have the same file: %s' % os.path.join(root, x)
                assert False

    with open(conf_file_name, 'w') as mf:
        mf.write(template)

    push_local_changes(mygit, target_branch, project)

def main():
    """The main body"""

    print '---[JOB STARTED]----------------------------------------'

    PROJECT_NAME = os.getenv('PROJECT_NAME')
    REPO_ARCH_MAPPING = ast.literal_eval(os.getenv('REPO_ARCH_MAPPING'))
    ENABLE_SNAPSHOT = os.getenv('ENABLE_SNAPSHOT') == 'true'
    ENABLE_PRERELEASE = os.getenv('ENABLE_PRERELEASE') == 'true'
    CONF_DIR = os.getenv('CONF_DIR')
    SNAPSHOT_DIR = os.getenv('SNAPSHOT_DIR')

    print 'PARAMETERS\n===='
    print PROJECT_NAME
    print REPO_ARCH_MAPPING
    print ENABLE_SNAPSHOT
    print ENABLE_PRERELEASE
    print CONF_DIR
    print '====\n'

    configure_snapshot_repo_conf(project=PROJECT_NAME, \
                                 repo_arch_map=REPO_ARCH_MAPPING, \
                                 enable_snapshot=ENABLE_SNAPSHOT, \
                                 enable_prerelease=ENABLE_PRERELEASE, \
                                 conf_dir=CONF_DIR, \
                                 snapshot_dir=SNAPSHOT_DIR)

if __name__ == '__main__':
    sys.exit(main())

