#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#
# Copyright (C) 2016 Samsung
#
#    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 by dashboard
"""

import os
import re
import sys
import shutil
import json

from xml.dom import minidom
import xml.etree.ElementTree as ElementTree

from gbp.git.repository import GitRepositoryError
from gitbuildsys.errors import ObsError
from osc import core

from common.buildservice import BuildService
from common.buildtrigger import trigger_info, trigger_next
from common import runner
from datetime import datetime
from common.buildmonitor_extention import BuildMonitorExtention
from common.upload_service import upload_obs_service, UploadError

# set default char-set endcoding to utf-8
reload(sys)
sys.setdefaultencoding('utf-8') # pylint: disable-msg=E1101

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

def obs_project_restartbuild(build, prj, pkg, repo=None, arch=None):
    """
    obs project clean
    """
    try:
        if pkg:
            if not build.exists(prj, pkg):
                raise LocalError("Not existes project %s: %s" % (prj,pkg))
        else:
            raise LocalError("Not existes project %s: %s" % (prj, pkg))

        build.restartbuild(prj, pkg, arch, repo)
        print "%s project restartbuild pakcage : %s " %(prj, pkg)
    except:
        raise LocalError("Unable to restartbuild the %s pacakge in %s project  " % (pkg, prj))

def obs_project_cleanbuild(build, prj, pkg=None, repo=None, arch=None, code=None):
    """
    obs project clean
    """
    try:
        if pkg == 'All':
            pkg = None
        elif pkg:
            if not build.exists(prj, pkg):
                raise LocalError("Not existes project %s: %s" % (prj,pkg))
        else:
             if not build.exists(prj):
                raise LocalError("Not existes project %s" % (prj))

        build.wipebinaries(prj, pkg, arch, repo, code)
        print "%s project clean..." %(prj)
    except:
        raise LocalError("Unable to cleanbuild the %s pacakge in %s project" % (pkg, prj))

def obs_project_rebuild(build, prj, pkg=None, repo=None, arch=None, code=None):
    """
    obs project rebuild
    """

    #code = 'failed'
    try:
        if pkg == 'All':
            pkg = None
        elif pkg:
            if not build.exists(prj, pkg):
                raise LocalError("Not existes project %s: %s" % (prj,pkg))
        else:
             if not build.exists(prj):
                raise LocalError("Not existes project %s" % (prj))

        target = None
        if repo and arch:
            target = '{}/{}'.format(repo, arch)
        build.rebuild(prj, pkg, target, code)
        print "%s project rebuilding..." %(prj)
    except:
        raise LocalError("Unable to rebuild the %s pacakge in %s project" % (pkg, prj))

def obs_project_delete_pkg(build, prj, pkg):
    """
    obs project delete package
    """
    try:
        if pkg:
            if not build.exists(prj, pkg):
                raise LocalError("Project or package does not exists (%s/%s)" % (prj,pkg))
        else:
            raise LocalError("Project does not exists (%s)" % (prj))

        build.delete_package(prj, pkg)
        print "%s project delete package : %s." %(prj, pkg)
    except:
        raise LocalError("Unable to delete the %s pacakge in %s project" % (pkg, prj))

def obs_project_undelete_pkg(build, prj, pkg):
    """
    obs project undelete package
    """
    try:
        if pkg:
            if build.exists(prj, pkg):
                raise LocalError("Project or package already exists (%s/%s)" % (prj,pkg))
        else:
            raise LocalError("Project already exists (%s)" % (prj))

        build.undelete_package(prj, pkg)
        build.runservice(prj, pkg)
        print "%s project undelete package : %s." %(prj, pkg)
    except:
        raise LocalError("Unable to undelete the %s pacakge in %s project" % (pkg, prj))

def obs_project_link_pkg(build, prj, src_pkg, dst_pkg):
    """
    obs project link package
    """
    try:
        build.create_link_pac(prj, src_pkg, prj, dst_pkg)
        print "%s project link package : %s -> %s" %(prj, src_pkg, dst_pkg)
    except:
        raise LocalError("Unable to linkpac the %s -> %s pacakge in %s project" % (src_pkg, dst_pkg, prj))

def obs_project_config(build, prj, config):
    """
    obs create project
    """
    try:
        if build.exists(prj):
            # set project config
            build.set_project_config(prj, config)
            print "\nTarget project %s: config" %(prj)
            return True
        else:
            raise LocalError("Unable to edit project config :  %s project" % (prj))
    except:
        raise LocalError("Unable to edit project config :  %s project" % (prj))

def obs_project_create_prj(build, prj, info=None, meta=None, config=None):
    """
    obs create project
    """
    try:
        if not build.exists(prj):
            try:
                build.create_project(prj, None, description=json.dumps(info))
            except:
                raise LocalError("Unable to create project %s: %s" % (prj))

            if meta:
                # set meta
                xml_meta = ElementTree.fromstringlist(meta)
                #change the target project name
                xml_meta.set('name',prj)

                print ElementTree.tostring(xml_meta)
                build.set_meta(ElementTree.tostring(xml_meta), prj)
            # set project config
            #print config
            build.set_project_config(prj, config)

            #enable debuginfo flag
            build.disable_build_flag(prj, repo = None, flag="debuginfo", status="enable")
            print "\nTarget project %s created" %(prj)
            return True
        else:
            print "\nTarget project %s exist" %(prj)
            return False
    except:
        raise LocalError("Unable to create project %s: %s" % (prj))

def obs_project_add_pkg(build, prj, pkg, git_url, git_prj, git_rev):
    """
    obs project add package
    """

    if build.exists(prj) and not build.exists(prj, pkg):
        try:
            upload_obs_service(git_url, git_prj, "", \
                  git_rev, prj, build, pkg)
            return True
        except:
            raise LocalError("Unable to add %s pacakge in %s project" % (pkg, prj))
    else:
        raise LocalError("Warning: target project %s doesn't exist" % prj)

def main():

    """
    Script entry point.
    """

    print '---[JOB STARTED: obs project manager]-------------------------'
    id = os.getenv("ID")
    submitter = os.getenv("SUBMITTER")
    decision = os.getenv("DECISION")
    project = os.getenv("PROJECT")
    package = os.getenv("PACKAGE")
    config = os.getenv("CONFIG")

    src_pkg = os.getenv("SRCPKG")
    dst_pkg = os.getenv("DSTPKG")

    repo = os.getenv("REPO")
    arch = os.getenv("ARCH")
    comment = os.getenv("COMMENT")

    print "DECISION = ", decision
    print "PROJECT = ", project
    print "PACKAGE = ", package

    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)
    bm_ext = BuildMonitorExtention()

    #check project
    #Check if we've got required field in env
    failures = ''
    try:
        if decision is None :
            raise LocalError("Unable to Projec manager...")

        if decision == 'rebuild':
           obs_project_rebuild(build, project, package, repo, arch)
        elif decision == 'clean':
           obs_project_cleanbuild(build, project, package)
        elif decision == 'restart':
           obs_project_restartbuild(build, project, package)
        elif decision == 'delpkg':
           obs_project_delete_pkg(build, project, package)
        elif decision == 'undelpkg':
           obs_project_undelete_pkg(build, project, package)
        elif decision == 'linkpkg':
           obs_project_link_pkg(build, project, src_pkg, dst_pkg)
        elif decision == 'config':
           obs_project_config(build, project, config)
        elif decision == 'create':
           obs_project_create_prj(build, project, config)
        elif decision == 'addpkg':
           git_url = 'ssh://%s:%s' % (os.getenv('GERRIT_HOSTNAME_EXTERNAL'),
                                      os.getenv('GERRIT_SSHPORT'))
           git_prj = os.getenv("GITPRJ")
           git_rev = os.getenv("GITREV")
           print "GITPRJ = ", git_prj
           print "GITREV = ", git_rev
           obs_project_add_pkg(build, project, package, \
                               git_url, git_prj, git_rev)
        else:
           print "%s decision is not defined" %(decision)
           failures = "%s decision is not defined" %(decision)
    except LocalError, exc:
        failures = (str(exc))
    except ObsError, error:
        failures = (str(exc))
    finally:
        if id is not None and id != "-1":
            bm_ext.update_project_mgr_log(id, failures)
        elif id is None and decision == 'rebuild' and comment.startswith('Digest mismatch'):
            bm_ext.create_project_mgr_log('robot', decision, project, package, comment, failures)
    
    return 0

if __name__ == '__main__':
    try:
        exit_status = main()
    except Exception as err:
        print err
        exit_status = 1

sys.exit(exit_status)
 
