#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014 Intel, Inc.
#
#    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 code is called when create snapshot.
"""

import os
import sys
import shutil
import re

from xml.dom import minidom

from common.buildtrigger import trigger_info, trigger_next
from common.buildservice import BuildService
from common.utils import sync

def update_buildlog_in_buildmonitor(package_build_dict, download_url,
        repo_path, proj, repo, target_path):
    data = {}
    data['bm_stage'] = "UPDATE_BUILD_LOG"
    data['project'] = proj
    data['repo'] = repo
    data['base_url'] = os.path.join(download_url, repo_path, target_path)
    data['pkgs'] = {}

    for (pkg_name, arch), (status, dummy, path_to_log) in \
            package_build_dict.items():
        if arch not in data['pkgs']:
            data['pkgs'][arch] = {}

        data['pkgs'][arch][pkg_name] = os.path.join(arch, status,
                                  "%s.buildlog.txt" % pkg_name)
    trigger_next("BUILD-MONITOR-%s" % repo, data)

def restructure_output_dir(package_build_dict, target_path):
    """ Put the logs in request structure
    """

    for (pkg_name, arch), (status, dummy, path_to_log) in \
            package_build_dict.items():
        try:
            shutil.copy(path_to_log, os.path.join(target_path,
                                                  arch,
                                                  status,
                                                  "%s.buildlog.txt" %pkg_name))
        except IOError, err:
            if err.errno == 2:
                # Directory not exists, just create it and copy again
                os.makedirs(os.path.join(target_path, arch, status))
                shutil.copy(path_to_log,
                            os.path.join(target_path,
                                         arch,
                                         status,
                                         "%s.buildlog.txt" %pkg_name))
            else:
                raise IOError(err)

def collect_build_data(base_path):
    """ Collect package build information
    """
    package_build_dict = {}

    for root, dummy, files in os.walk(base_path):
        if 'status' in files and 'logfile' in files:
            with open(os.path.join(root, 'status')) as xml_fh:
                xml_root = minidom.parse(xml_fh)
                status_element = xml_root.getElementsByTagName('status')[0]
                status = status_element.getAttribute('status')

                readytime_element = \
                    status_element.getElementsByTagName('readytime')[0]

                readytime = readytime_element.childNodes[0].data
                arch = os.path.basename(os.path.dirname(root))

                package_build_dict[(os.path.basename(root), arch)] = \
                    (status, readytime, os.path.join(root, 'logfile'))

    return package_build_dict

def main():
    """Script entry point.
    """

    print '---[JOB STARTED: buildlog ]-------------------------'

    build_base_path = os.getenv("PATH_OBS_BUILD_BASE", "/srv/obs/build")

    sync_out_dir = os.path.join(os.getenv('WORKSPACE'),
                                    'outdir')

    content = trigger_info(os.getenv("TRIGGER_INFO"))

    sync_dest = os.path.join(os.getenv('IMG_SYNC_DEST_BASE'),
                             content['repo_path'])

    project = content.get("project")

    #TODO: backend slave selection.
    backend_label = os.getenv('BACKEND_SELECTION', 'BACKEND_01')
    if os.getenv('%s_REGEX' % backend_label) and \
        re.search(r'%s' % os.getenv('%s_REGEX' % backend_label), project) is None:
        print 'Backend(%s) selection mismatch for %s.' % (backend_label, project)
        return

    obs_api = os.getenv("OBS_API_URL")
    obs_user = os.getenv("OBS_API_USERNAME")
    obs_passwd = os.getenv("OBS_API_PASSWD")
   
    build = BuildService(obs_api, obs_user, obs_passwd)

    for repository in content.get("repo").keys():
        project_logs_base = os.path.join(build_base_path,
                                         project,
                                         repository)
        # Get the build data dict
        packages_data = collect_build_data(project_logs_base)

        # Restructure the directory for publishing
        restructure_output_dir(packages_data,
                               os.path.join(sync_out_dir,
                                            'builddata',
                                            'buildlogs',
                                            repository))
        update_buildlog_in_buildmonitor(packages_data,
                                        os.getenv("URL_PUBLIC_REPO_BASE"),
                                        content['repo_path'],
                                        project,
                                        repository,
                                        os.path.join('builddata',
                                                     'buildlogs',
                                                     repository))

    # Make file at packages depends of OBS
    os.makedirs(os.path.join(sync_out_dir,'builddata','depends'))
    reverse = 1
    repo_status = build.get_repo_state(project)

    for target_arch,status in repo_status.items():
        repo = target_arch.split("/")[0]
        arch = target_arch.split("/")[1]
        xml = build.get_dependson(project, repo, arch, None, reverse)

        file_name = os.path.join(sync_out_dir,'builddata','depends',"%s_%s_%s_revpkgdepends.xml"%(project,repo,arch))
        #print file_name
        with open(file_name, 'w') as xml_file:
            xml_file.write(xml)

    # Make file at packages revision of OBS
    packages_rev = dict()
    for package in build.get_package_list(project):
        packages_rev[package] = build.show_upstream_rev(project, package)
    file_name = os.path.join(sync_out_dir,'builddata','depends', '%s_pkgrevisions.xml' % project)
    #print str(packages_rev)
    with open(file_name, 'w') as rev_file:
        rev_file.write(str(packages_rev))

    # sync to donwload server
    sync(sync_out_dir, sync_dest)

    data={}
    data['obs_project'] = project
    data['action'] = "build_dep_graph"
    data['repo_path'] = content['repo_path']
    trigger_next("make_dep_graph", data)

    # TRIGGER NEXT SYNC-AWS
    if os.getenv("TRBS_SYNC_AWS_ENABLED", "0") != "0":
        data = {"repo_path": content['repo_path']}
        trigger_next('SYNC-AWS', data)

    # TRIGGER NEXT RSYNC-DOWNLOAD (MIRROR)
    if os.getenv("RSYNC_DOWNLOAD_ENABLED", "0") != "0":
        trigger_next('RSYNC_DOWNLOAD', content)

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