#!/usr/bin/env python
#
# Copyright (c) 2014, 2015, 2016 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.
#
"""This job is triggered by gerrit submit ref update event for preloaded app.
   It will generate tizen app package(.tpk) and requests prerelease routine.
"""

import os
import sys
import shutil
import re
import glob
import zipfile
import requests
from pprint import pprint
import base64
import json

from datetime import datetime
from time import sleep
import xml.etree.cElementTree as ElementTree

sys.path.insert(1, os.path.join(sys.path[0], '..'))

from common.git import Git, clone_gitproject
from common.tizen_studio_docker import TizenStudio
from common.send_mail import prepare_mail
from common.buildtrigger import trigger_next

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

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

def retrieve_project_property(src_git, tag):
    """ Search APP properties """

    ret_prop = {}

    def get_git_repo_size(quiet=True):
        if quiet == False:
            src_git._git_inout('gc', ['--quiet'])
        pack_size, t_err, t_code = src_git._git_inout('count-objects', ['-v'])
        pack_size = pack_size[pack_size.find('size-pack:')+11:].split('\n')[0]
        print '"UNPACK-SIZE": \"%d\"' % int(pack_size)
    try:
        get_git_repo_size()
    except Exception as err:
        print repr(err)

    def retrieve_license(src_root):
        LICENSE_FORM = r'.*Licensed under the (.*) License, Version (.*) \(the \"License\"\).*;'
        sdk_license = None
        for f in os.listdir(src_root):
            if os.path.isfile(os.path.join(src_root, f)) and f.startswith('LICENSE'):
                with open(os.path.join(src_root, f), 'r') as r_file:
                    for x in r_file.readlines():
                        matchline = re.search(LICENSE_FORM, x)
                        if matchline:
                            sdk_license = '%s-%s' % \
                                (matchline.groups()[0], matchline.groups()[1])
                            print 'LICENSE %s from %s' % (sdk_license, f)
        if sdk_license is None:
            sdk_license = 'Samsung'
        return sdk_license


    def retrieve_properties_from_project_def(src_root):

        sdk_package = ''
        sdk_version = ''
        sdk_profile = ''
        sdk_web_name = ''
        ret_error = ''
        app_type = None

        MANIFEST = 'tizen-manifest.xml'


        # As guided, the last is the main app from multi project listup.
        def_file_list = []
        # Multi project
        multiproject_list_f = os.path.join(src_root, 'WORKSPACE')
        if os.path.isfile(multiproject_list_f):
            with open(multiproject_list_f, 'r') as r_file:
                for x in r_file.readlines():
                    if os.path.isdir(os.path.join(src_root, x.rstrip())):
                        if os.path.isfile(os.path.join(src_root, x.rstrip(), 'tizen-manifest.xml')):
                            def_file_list.append(os.path.join(src_root, x.rstrip(), 'tizen-manifest.xml'))
                        elif os.path.isfile(os.path.join(src_root, x.rstrip(), 'config.xml')):
                            def_file_list.append(os.path.join(src_root, x.rstrip(), 'config.xml'))
        else:
            # Single project
            if os.path.isfile(os.path.join(src_root, 'tizen-manifest.xml')):
                def_file_list.append(os.path.join(src_root, 'tizen-manifest.xml'))
            if os.path.isfile(os.path.join(src_root, 'config.xml')):
                def_file_list.append(os.path.join(src_root, 'config.xml'))

        #for def_file in def_file_list:
        #TODO: Should be the last item
        def_file = def_file_list[-1]
        if os.path.isfile(def_file):
            print 'Property file: %s' % def_file
            try:
                with open(def_file, 'r') as df:
                    manifest_dump = df.read()
                if os.path.basename(def_file) == 'tizen-manifest.xml':
                    xmlstring = re.sub('\\sxmlns="[^"]+"', '', manifest_dump, count=1)
                    _root = ElementTree.fromstring(xmlstring)
                    for child in _root:
                        if child.tag == 'profile':
                            sdk_profile = child.attrib.get('name', sdk_profile)
                            print 'Set SDK_PROFILE:[%s]' % sdk_profile
                    sdk_package = _root.attrib.get('package', sdk_package)
                    sdk_version = _root.attrib.get('version', sdk_version)
                    app_type = 'tpk'
                elif os.path.basename(def_file) == 'config.xml':
                    xmlstring = re.sub('\\sxmlns:tizen="[^"]+"', '', manifest_dump, count=1)
                    xmlstring = re.sub('\\sxmlns="[^"]+"', '', manifest_dump, count=1)
                    xmlstring = xmlstring.replace('tizen:', '')
                    _root = ElementTree.fromstring(xmlstring)
                    for child in _root:
                        if child.tag == 'profile':
                            sdk_profile = child.attrib.get('name', sdk_profile)
                            print 'Set SDK_PROFILE:[%s]' % sdk_profile
                        elif child.tag == 'application':
                            sdk_package = child.attrib.get('package', sdk_package)
                            print 'Set SDK_PACKAGE:[%s]' % sdk_package
                            sdk_web_name = child.attrib.get('id', sdk_package)
                            if "%s." % sdk_package in sdk_web_name:
                                sdk_web_name = sdk_web_name.replace("%s." % sdk_package, "")
                            print 'Set SDK_WEB_NAME:[%s]' % sdk_web_name
                        #elif child.tag == 'name' and child.attrib == {}:
                        #    sdk_web_name = child.text
                        #    print 'Set SDK_WEB_NAME:[%s]' % sdk_web_name
                    sdk_version = _root.attrib.get('version', sdk_version)
                    app_type = 'wgt'
            except Exception as err:
                ret_error = err
        if not sdk_profile:
            sdk_profile = ''
        #    ret_error += 'ERROR: No "profile" tag in property file(tizen-manifest.xml)'
        print 'TIZEN-MANIFEST.XML (%s) (%s)' % (sdk_package, sdk_version)
        return {'sdk_package': sdk_package, 'sdk_version': sdk_version, \
                'sdk_profile': sdk_profile, 'ret_error': ret_error, \
                'app_type': app_type, 'sdk_web_name': sdk_web_name}

    def retrieve_commit_id(src_git):
        commit_id = src_git.rev_parse('HEAD')
        print 'commit from (HEAD) = %s' % (commit_id)
        return commit_id

    def retrieve_revision_number(src_git, tag):
        _ret = {}
        try:
            _ret['revision_number'] = src_git.rev_parse(tag)
        except Exception as err:
            print repr(err)
        print 'revision from (%s) = %s' % (tag, _ret)
        return _ret

    def retrieve_commit_message(src_git):
        t_outs, t_err, t_code = src_git._git_inout('log', ['--format=%B', '-n 1'])
        commit_message = t_outs[:t_outs.rfind("\nChange-Id: ")].rstrip() + '\n'
        print "author comment : %s" % commit_message
        return commit_message

    def retrieve_sr_message(src_git, tag):
        t_outs, t_err, t_code = src_git._git_inout('show', [tag, '--format=##chkstr:%b'])
        sr_message = '\n'.join(t_outs[:t_outs.rfind("##chkstr:")].split('\n')[3:])
        print "sr comment from(%s) : [%s]" % (tag, sr_message.rstrip())
        return sr_message

    def retrieve_committer(src_git):
        t_outs, t_err, t_code = src_git._git_inout('log', ['--format=%cE', '-n 1'])
        committer = t_outs.strip().rstrip().replace('<','').replace('>','')
        print "committer : %s" % committer
        return committer

    def retrieve_submitter(src_git, tag):
        t_outs, st_err, st_ret = src_git._git_inout('for-each-ref', \
                    ['--count=1', '--sort=-taggerdate', \
                     '--format=%(taggeremail)', 'refs/tags/%s' % tag])
        submitter = t_outs.strip().rstrip().replace('<','').replace('>','')
        print "submitter : %s" % submitter
        return submitter

    def retrieve_commit_date(src_git):
        t_outs, t_err, t_code = src_git._git_inout('log', ['--format=%ci', '-n 1'])
        commit_date = t_outs
        print "commit_date : %s" % commit_date
        return commit_date

    def retrieve_submit_date(src_git, tag):
        submit_date, sd_err, sd_ret = src_git._git_inout('for-each-ref', \
                    ['--count=1', '--sort=-taggerdate', \
                     '--format=%(taggerdate:iso)', 'refs/tags/%s' % tag])
        print "submit_date : %s" % submit_date
        return submit_date

    ret_prop.update(retrieve_properties_from_project_def(src_git.path))
    ret_prop['commit_id'] = retrieve_commit_id(src_git)
    ret_prop['revision_number'] = retrieve_revision_number(src_git, tag).get('revision_number', \
                                  ret_prop.get('commit_id'))
    ret_prop['commit_message'] = retrieve_commit_message(src_git)
    ret_prop['sr_message'] = retrieve_sr_message(src_git, tag)
    ret_prop['sdk_license'] = retrieve_license(src_git.path)

    ret_prop['committer'] = retrieve_committer(src_git)
    ret_prop['submitter'] = retrieve_submitter(src_git, tag)
    ret_prop['commit_date'] = retrieve_commit_date(src_git)
    ret_prop['submit_date'] = retrieve_submit_date(src_git, tag)

    for r in ret_prop:
        if ret_prop[r]:
            print '  [%s]: %s' % (r, ret_prop[r].rstrip())
        else:
            print '  [%s]: %s' % (r, ret_prop[r])

    return ret_prop

def fetch_source(src_root, project, branch=None, tag=None):
    """ Cloning APP source code """

    print 'Cloning source code %s' % src_root
    if True:
        if not clone_gitproject(project, src_root, \
                                git_cache_dir='nonexist'):
            raise LocalError('Error cloning project %s' % project)
    working_git = Git(src_root)
    if tag is not None:
        working_git.checkout(tag)
        return working_git, tag
    elif branch is not None:
        working_git.checkout(branch)
        return working_git, branch

def zipping_workspace(src_root):
    """ Create tarball to share source code easily between VM machine """

    def ZipDir(inputDir, outputZip):
        '''Zip up a directory and preserve symlinks and empty directories'''
        zipOut = zipfile.ZipFile(outputZip, 'w', compression=zipfile.ZIP_DEFLATED)

        rootLen = len(os.path.dirname(inputDir))
        def _ArchiveDirectory(parentDirectory):
            contents = os.listdir(parentDirectory)
            #store empty directories
            if not contents:
                archiveRoot = parentDirectory[rootLen:].replace('\\', '/').lstrip('/')
                zipInfo = zipfile.ZipInfo(archiveRoot+'/')
                zipOut.writestr(zipInfo, '')
            for item in contents:
                fullPath = os.path.join(parentDirectory, item)
                if fullPath.endswith('/.git'): continue
                if os.path.isdir(fullPath) and not os.path.islink(fullPath):
                    _ArchiveDirectory(fullPath)
                else:
                    archiveRoot = fullPath[rootLen:].replace('\\', '/').lstrip('/')
                    if os.path.islink(fullPath):
                        zipInfo = zipfile.ZipInfo(archiveRoot)
                        zipInfo.create_system = 3
                        # long type of hex val of '0xA1ED0000L',
                        # say, symlink attr magic...
                        zipInfo.external_attr = 2716663808
                        zipOut.writestr(zipInfo, os.readlink(fullPath))
                    else:
                        zipOut.write(fullPath, archiveRoot, zipfile.ZIP_DEFLATED)
        _ArchiveDirectory(inputDir)
        zipOut.close()

    current_dir = os.getcwd()
    os.chdir(os.path.dirname(src_root))
    src_d = os.path.basename(src_root)
    out_f = src_d + '.zip'
    ZipDir(src_d, out_f)
    os.chdir(current_dir)

def generate_spec_file(tizen_studio, src_git, prop, sourceData, confData, ciData, app_type):
    """ Use spec file template """

    found_archs = []
    archs_lookup = [['i386', 'i486', 'i586', 'i686', 'x86'], \
                    ['arm', 'armv7l'], \
                    ['x86_64'], \
                    ['aarch64']]

    internal_package_name = prop.get('sdk_package')
    if app_type == 'wgt':
        internal_package_name = prop.get('sdk_web_name')

    for fn in os.listdir(tizen_studio.builddir):
        if app_type == 'tpk':
            mtch = re.search(r'(.*)-([0-9.]+)-(.*)(?<!-debug).tpk', fn)
            if mtch and mtch.groups() and len(mtch.groups()) == 3:
                for l in archs_lookup:
                    if mtch.groups()[2] in l:
                        found_archs.extend(l)
                        break
        elif app_type == 'wgt':
            full_arch = []
            for l in archs_lookup:
                full_arch.extend(l)
            mtch = re.search(r'(.*)-(%s)(?<!-debug).wgt' % '|'.join(full_arch), fn)
            if mtch and mtch.groups() and len(mtch.groups()) == 2:
                for l in archs_lookup:
                    _a = mtch.groups()[1]
                    if _a in l:
                        found_archs.extend(l)
                        _app_name = prop.get('sdk_web_name')
                        _app_arch = _a
                        _app_version = prop.get('sdk_version')
                        #Append version info in filename
                        os.rename(os.path.join(tizen_studio.builddir, fn), \
                                  os.path.join(tizen_studio.builddir, \
                                  "%s-%s-%s.wgt" % (_app_name, _app_version, _app_arch)))
                                  #fn.replace(_a, '%s-%s' % (prop.get('sdk_version'), _a))))
                        break

    found_archs = list(set(found_archs))
    print 'found_archs=%s' % found_archs

    # SPEC configuration
    group = ''
    sdk_license = prop.get('sdk_license')
    summary = ''
    license = ''
    if os.path.isdir(os.path.join(src_git.path, 'packaging')):
        for filename in os.listdir(os.path.join(src_git.path, 'packaging')):
            if re.match('.*\.spec', filename):
                with open(os.path.join(src_git.path, 'packaging', filename)) as f_spec:
                    for x in f_spec.readlines():
                        if group == '' and re.match('Group:.*', x):
                            group = x.split(':')[1].strip().rstrip()
                        if license == '' and re.match('License:.*', x):
                            license = x.split(':')[1].strip().rstrip()
                        if summary == '' and re.match('Summary:.*', x):
                            summary = x.split(':')[1].strip().rstrip()

    if group == '' or group is None: group = 'N/A'
    if license == '' or license is None: license = 'N/A'
    if summary == '' or summary is None: summary = sourceData.get('PACKAGE_NAME')

    if sdk_license is not None and sdk_license != '':
        license = sdk_license

    vcs = '#VCS_FROM:   %s' % (sourceData.get('GIT_PATH') + "#" + prop.get('commit_id'))
    vcs_desc = vcs.split(' ')[-1]

    if os.getenv('EXCLUDE_ARCH'):
        exclude_arch = 'ExcludeArch: '
        for exa in os.getenv('EXCLUDE_ARCH').split(','):
            exclude_arch = exclude_arch + ' ' + exa
    else:
        exclude_arch = ''

    if found_archs is not None:
        exclusive_arch = 'ExclusiveArch: '
        for exa in found_archs:
            exclusive_arch = exclusive_arch + ' ' + exa
    else:
        exclusive_arch = ''

    rpm_build_mode = '%{nil}'

    spec_template = tizen_studio.get_template('spec')
    spec_template = spec_template.replace( \
                        '__OBS_PACKAGE_NAME__', sourceData.get('PACKAGE_NAME')).replace( \
                        '__VCS__', vcs).replace( \
                        '__ROOTSTRAP_VERSION__', tizen_studio.built_version).replace( \
                        '__SUMMARY__', summary).replace( \
                        '__VERSION__', prop.get('sdk_version')).replace( \
                        '__GROUP__', group).replace( \
                        '__LICENSE__', license).replace( \
                        '__EXCLUSIVE_ARCH__', exclusive_arch).replace( \
                        '__EXCLUDE_ARCH__', exclude_arch).replace( \
                        '__TIZEN_STUDIO_PACKAGE_NAME__', internal_package_name).replace( \
                        '__BUILD_MODE__', rpm_build_mode).replace( \
                        '__VCS_DESCRIPTION__', vcs_desc).replace( \
                        '__APP_TYPE__', app_type)
    return spec_template

def post_processing(tizen_studio, src_git, prop, \
                    sourceData, confData, ciData, builddir):
    """ Create SR of the generated tpks thru git tagging """

    print 'TizenStudio: builddir: %s' % tizen_studio.builddir

    postData = {'status': 'PASS', 'error': None}

    #TODO: Check app type (tpk|wgt)
    app_type = None
    for filename in os.listdir(builddir):
        if re.match('.*\.(tpk|wgt)', filename):
            if filename.endswith('.tpk'):
                app_type = 'tpk'
            elif filename.endswith('.wgt'):
                app_type = 'wgt'

    spec = generate_spec_file(tizen_studio, src_git, prop, sourceData, confData, ciData, app_type)
    print 'SPEC:\n%s' % spec

    # Checkout _tpk branch and push the tpks and tag it
    new_branch = sourceData.get('NEW_BRANCH')
    new_tag = sourceData.get('NEW_TAG')
    # Register local git user
    with open(os.path.join(src_git.path, '.git', 'config'), 'a') as gitconfig:
        gitconfig.write('[user]\n\tname = %s\n\temail = %s\n' \
                        % (sourceData.get('USER_NAME'), sourceData.get('USER_EMAIL')))
    # Checkout tpk branch
    if src_git.has_branch('origin' + new_branch, remote = True):
        print 'Branch (%s) already exist' % new_branch
        src_git.checkout(new_branch)
    else:
        src_git._git_inout('checkout', ['--orphan', '%s' % new_branch])
        src_git._git_inout('rm', ['-rf', '.'])
    print src_git._git_inout('fetch', ['origin'])[0]
    print src_git._git_inout('reset', ['origin/' + new_branch, '--hard'])[0]
    try:
        chk_tag = src_git.rev_parse(new_tag)
        print 'Checking tag [%s]' % chk_tag
        if chk_tag:
            print 'Tag(%s) already exist.' % new_tag
            # Force remove previous tag...
            if True:
                src_git.delete_tag(new_tag)
                src_git.remove_tag_from_remote('origin', new_tag)
    except Exception as err:
        pass
    try:
        src_git.remove_files('*')
    except:
        pass
    try:
        src_git.remove_files('packaging/*')
    except:
        pass
    if not os.path.exists(os.path.join(src_git.path, 'packaging')):
        os.makedirs(os.path.join(src_git.path, 'packaging'))
    for filename in os.listdir(builddir):
        if re.match('.*\.(tpk|wgt)', filename):
            print 'Found [%s].' % filename
            shutil.copy(os.path.join(builddir, filename), os.path.join(src_git.path, filename))
    try:
        src_git.add_files('*.tpk', True)
    except:
        pass
    try:
        src_git.add_files('*.wgt', True)
    except:
        pass
    with open(os.path.join(src_git.path, 'packaging', \
        sourceData.get('PACKAGE_NAME') + '.spec'), 'w') as sf:
        sf.write('%s' % spec)
    src_git.add_files('packaging/*.spec', True)

    commit_message = "[ABS] %s\nReference: %s\nCommit id: %s\nRequested by: %s\n" \
                     "SDK rootstrap version: %s" \
                     % (prop.get('commit_message'), sourceData.get('TAG_NAME'), \
                        prop.get('commit_id'), \
                        sourceData.get('USER_EMAIL'), tizen_studio.built_version)
    print commit_message
    src_git.commit_staged(commit_message)
    commit_id_new = src_git.rev_parse('HEAD')
    print 'commit from new HEAD: %s' % commit_id_new

    if True:
        # Just copy back to share directory
        if not os.path.exists('/share/QB_OUT'):
            os.makedirs('/share/QB_OUT/%s' % os.path.basename(src_git.path))
        for of in glob.glob(os.path.join(src_git.path, '*')):
            bof = os.path.basename(of)
            if os.path.isdir(of) and not of.endswith('/.git'):
                shutil.copytree(of, os.path.join('/share/QB_OUT/', \
                    os.path.basename(src_git.path), bof))
            elif os.path.isfile(of):
                shutil.copy(of, os.path.join('/share/QB_OUT/', \
                    os.path.basename(src_git.path), bof))
        for of in os.listdir(builddir):
            if re.match('.*(\.log|rsver|tizen_studio_.*)', of):
                shutil.copy(os.path.join(builddir, of), os.path.join('/share/QB_OUT/', of))
        with open(os.path.join('/share/QB_OUT/', 'new_tpk_commit_id'), 'w') as ntc:
            ntc.write('%s' % commit_id_new)

    push_err_msg = ''
    push_retry = 5
    while push_retry > 0:
        try:
            src_git.push(repo = 'origin', src = '%s' % new_branch, force=True)
            break
        except Exception as err:
            print 'git push exception: %s' % repr(err)
            push_err_msg = push_err_msg + '\n' + str(err)
            push_retry -= 1
            sleep(5)
    if not push_retry:
        postData['status'] = 'FAIL'
        postData['error']  = 'Pushing binary error.\n%s' % push_err_msg
        return postData

    message = '%s\n' \
        '[ABS] Ready.\n' \
        '- Original Tag: %s (%s)\n' \
        '- Original Commit: %s\n' \
        '- Requested By: %s\n' \
        % (prop.get('sr_message'), sourceData.get('TAG_NAME'), \
           prop.get('revision_number'), prop.get('commit_id'), sourceData.get('USER_EMAIL'))
    try:
        src_git.create_tag(name=new_tag, msg=message, commit=commit_id_new)
    except Exception as err:
        postData['status'] = 'FAIL'
        postData['error']  = 'Creating tag error.\n%s' % repr(err)
        return postData

    try:
        revision_number_new = src_git.self.rev_parse(new_tag)
    except:
        revision_number_new = prop.get('commit_id')

    push_err_msg = ''
    push_retry = 5
    while push_retry >0:
        try:
            src_git.push_tag('origin', new_tag)
            break
        except Exception as err:
            print 'Cannot push tag %s (%s)' % (new_tag, str(err))
            push_err_msg = push_err_msg + '\n' + str(err)
            push_retry -= 1
            sleep(5)
    if not push_retry:
        postData['status'] = 'FAIL'
        postData['error']  = 'Pushing tag error.\n%s' % push_err_msg
        return postData

    return postData

def make_data():

    # Fetch required variables...
    sourceData = {'PROJECT'   : os.getenv('PROJECT'), \
                  'GIT_PATH'  : os.getenv('GIT_PATH'), \
                  'REVISION'  : os.getenv('REVISION'), \
                  'BRANCH'    : os.getenv('BRANCH'), \
                  'TAG_NAME'  : os.getenv('TAG_NAME'), \
                  'USER_EMAIL': os.getenv('USER_EMAIL'), \
                  'PACKAGE_NAME_FROM_MAPPING': os.getenv('PACKAGE_NAME_FROM_MAPPING') \
                 }
    pprint(sourceData)
    confData   = {'ABS_CLI_SCRIPT_GIT'    : os.getenv('ABS_CLI_SCRIPT_GIT'), \
                  'ROOTSTRAP_URL'         : os.getenv('ROOTSTRAP_URL'), \
                  #'SDK_SIGN_AUTHOR'       : os.getenv('SDK_SIGN_AUTHOR'), \
                  'ABS_ROOTSTRAP_URL'     : os.getenv('ABS_ROOTSTRAP_URL'), \
                  'ABS_MAILINGLIST'       : os.getenv('ABS_MAILINGLIST'), \
                  'SDK_SIGN_GIT'          : os.getenv('SDK_SIGN_GIT'), \
                  'SDK_TOOL_GIT'          : os.getenv('SDK_TOOL_GIT'), \
                  'SDK_SIGN_AUTHOR'       : os.getenv('SDK_SIGN_AUTHOR'), \
                  'SDK_SIGN_DIST'         : os.getenv('SDK_SIGN_DIST'), \
                  'ABS_SDK_PACKAGE_SERVER': os.getenv('ABS_SDK_PACKAGE_SERVER'), \
                  'BUILD_MODE'            : os.getenv('BUILD_MODE'), \
                  'EXCLUDE_ARCH'          : os.getenv('EXCLUDE_ARCH') \
                 }
    pprint(confData)
    ciData     = {'ABS_WORKSPACE': os.getenv('ABS_WORKSPACE'), \
                  'JOB_NAME'     : os.getenv('JOB_NAME'), \
                  'BUILD_ID'     : os.getenv('BUILD_ID'), \
                 }
    if os.getenv('BUILD_CAUSE') is None:
        ciData['BUILD_CAUSE'] = 'GIT'
    else:
        ciData['BUILD_CAUSE'] = 'CHECK'
        confData['ABS_ROOTSTRAP_URL'] = os.getenv('BUILD_CAUSE').split(',')[1]
    pprint(ciData)
    return sourceData, confData, ciData

def make_work_directory(basedir, builddir):

    print 'BASEDIR: %s' % basedir
    if os.path.exists(basedir):
        shutil.rmtree(basedir)
    os.makedirs(builddir)
    if True:
        try:
            if os.path.isdir('/share/build'):
                shutil.rmtree('/share/build')
            elif os.path.islink('/share/build'):
                os.unlink('/share/build')
            else:
                os.remove('/share/build')
        except Exception as err:
            print err
        os.symlink(builddir, '/share/build')

def make_property_data(tag, branch, src_git, int_tag):

    pData = {}
    project_properties = retrieve_project_property(src_git, int_tag)
    pData['PACKAGE_NAME']   = project_properties.get('sdk_package')
    pData['PROFILE']        = project_properties.get('sdk_profile')
    pData['NEW_BRANCH']     = branch + '_tpk'
    if tag is not None:
        pData['NEW_TAG']    = tag.replace(branch, pData.get('NEW_BRANCH'))
    pData['COMMIT_ID']      = project_properties.get('commit_id')
    pData['COMMITTER']      = project_properties.get('committer')
    pData['COMMIT_DATE']    = project_properties.get('commit_date').strip()
    pData['COMMIT_MESSAGE'] = project_properties.get('commit_message').strip()
    pData['TAGGER']         = project_properties.get('submitter')
    pData['TAG_REVISION']   = project_properties.get('revision_number')
    pData['TAG_DATE']       = project_properties.get('submit_date').strip()
    pData['TAG_MESSAGE']    = project_properties.get('sr_message').strip()

    if project_properties.get('ret_error') != '':
        print 'You got property error:\n%s' % project_properties.get('ret_error')
        return None
    if 'sdk_license' not in project_properties or project_properties.get('sdk_license') is None:
        print 'No LICENSE provided.'
        return None

    return pData, project_properties

def rootstrap_update_process(tizenStudioInst, basedir, confData):

    if True:
        # Update rootstrap
        new_rs = confData.get('ABS_ROOTSTRAP_URL')
        supported_profiles = ['mobile', 'wearable']
        #FIXME: Check if url exists...
        new_rs = new_rs.replace('__RELEASE_ID__', 'latest')
        session = requests.Session()
        session.trust_env = False
        _r = session.get(new_rs)
        if _r.status_code != 200:
            # Search previous snapshot if latest have no rootstraps
            if '/latest/' in new_rs:
                # Download parent page and parse links
                rs_parent_url = new_rs.replace('latest/builddata/private-sdk-rootstrap/', '')
                _r = session.get(rs_parent_url)
                snapshot_list = []
                for sn in _r.text.split('\n'):
                    if 'alt="[DIR]"></td><td><a href="' in sn:
                        snapshot_list.append(sn.split('/</a></td>')[0].split('>')[-1])
                snapshot_list.sort(reverse=True)
                print 'snapshot_list: %s' % snapshot_list
                for sn in snapshot_list:
                    print "Check snapshot %s" % sn
                    _r = session.get(new_rs.replace('/latest/', '/%s/' % sn))
                    if _r.status_code == 200:
                        print 'Found latest at %s' % sn
                        new_rs = new_rs.replace('/latest/', '/%s/' % sn)
                        break
            else:
                print 'Non-latest will not search here'
        elif _r.status_code == 200:
            print 'We have latest...'
        tizenStudioInst.update_rootstrap(new_rs, None, profiles=supported_profiles)
    sys.stdout.flush()

def build_status_notification(status='PASS', reason=None, log=None, \
                              requesterEmail=None, ccList=None, \
                              mainProject=None, branch=None, \
                              gitPath=None, packageName=None, tagName=None, \
                              rootstrapVersion=None):

    TITLE  = '[ABS] %s (%s) %s' % (packageName, branch, status)
    HEADER = 'App Build System(ABS) inform you the Tizen Studio build result.\n' \
             '(ABS will trigger build if you issues an SR on preloaded app branch)\n\n'

    BODY   = '\n'

    BODY   += 'Result: %s\n' % status
    BODY   += 'Path: %s\n' % gitPath
    BODY   += 'Tag: %s\n' % tagName
    BODY   += 'Project: %s\n' % mainProject
    BODY   += 'Rootstrap: %s\n' % rootstrapVersion
    BODY   += 'Reason: %s\n' % reason
    BODY   += '\nFor detailed info, please visit %s/abs_rbs.code\n' % os.getenv('DASHBOARD_URL')
    BODY   += '\n'
    BODY   += '\n%s\n\n' % log

    FOOTER = '\n\n--------\n'\
             'Automatically generated by backend service.\n'

    emailTo = [requesterEmail]
    if ccList is not None:
        emailTo.extend(ccList)

    pprint(TITLE)
    pprint(BODY + FOOTER)
    pprint(emailTo)

    prepare_mail('status_noti.env', TITLE, BODY + FOOTER, 'abs.robot@tizen.org', emailTo)

def update_dashboard(stage, triggerCause, \
                     status, statusReason, \
                     s, e, c, k):

    try:
        data = {"event_type"               : stage, \
                "type"                     : triggerCause, \
                "project"                  : s.get('PROJECT'), \
                "git_path"                 : s.get('GIT_PATH'), \
                "commit_id"                : s.get('COMMIT_ID'), \
                "committer"                : s.get('COMMITTER'), \
                "commit_date"              : s.get('COMMIT_DATE'), \
                "commit_message"           : s.get('COMMIT_MESSAGE'), \
                "tag_name"                 : s.get('TAG_NAME'), \
                "tag_revision"             : s.get('TAG_REVISION'), \
                "tagger"                   : s.get('TAGGER'), \
                "tag_date"                 : s.get('TAG_DATE'), \
                "tag_message"              : s.get('TAG_MESSAGE'), \
                "tpk_git_tag"              : s.get('NEW_TAG'), \
                "status"                   : status, \
                "status_reason"            : statusReason, \
                "tizen_studio_version"     : k.get('tizen_studio_version'), \
                "tizen_studio_distribution": k.get('tizen_studio_distribution'), \
                "rootstrap_version"        : k.get('built_version'), \
                "infra"                    : 'LOCAL'}
        print 'update_dashboard'
        pprint(data)
        encoded_data = base64.b64encode(json.dumps(data))
        trigger_next('UPDATE_ABS_STATUS', data)
    except Exception as err:
        print repr(err)
        print 'Updating Dashboard Failed'

def start_build(options):
    """ Running build using Tizen Studio """

    print 'ENTER start_build'

    print options
    option = 'normal'
    if len(options) >= 1:
        option = options[1]

    sourceData, confData, ciData = make_data()

    print '\n"Title": "%s/%s"\n' % (os.path.basename(sourceData.get('GIT_PATH')), \
                                    sourceData.get('TAG_NAME'))

    # Working directory
    basedir = os.path.join(ciData.get('ABS_WORKSPACE'), ciData.get('BUILD_ID'))
    builddir = os.path.join(basedir, 'build')
    make_work_directory(basedir, builddir)

    # Fetch Source Code
    src_root = os.path.join(builddir, os.path.basename(sourceData.get('GIT_PATH')))
    src_git, int_tag = fetch_source(src_root, \
                                    sourceData.get('GIT_PATH'), branch=sourceData.get('BRANCH'), \
                                    tag=sourceData.get('TAG_NAME'))
    if src_git is None or int_tag is None:
        return 1
    print 'Got tag: [%s]' % int_tag

    propEnv, project_properties = make_property_data(sourceData.get('TAG_NAME'), \
                                      sourceData.get('BRANCH'), src_git, int_tag)
    if propEnv is None:
        return 1
    sourceData.update(propEnv)

    if sourceData.get('PACKAGE_NAME_FROM_MAPPING') is not None:
        print 'Set package_name from mapping: %s' % sourceData.get('PACKAGE_NAME_FROM_MAPPING')
        sourceData['PACKAGE_NAME'] = sourceData.get('PACKAGE_NAME_FROM_MAPPING')
    pprint(sourceData)

    # Make tarball to share source codes easily with vm machine
    zipping_workspace(src_root)

    parallel_jobs = '"-j 1"'

    #### Running command to launch Tizen Studio ####
    print '[ TizenStudio START ] %s' % (str(datetime.now()))
    sys.stdout.flush()

    tizenStudioInst = TizenStudio(baseDir=basedir, confData=confData)
    rootstrap_update_process(tizenStudioInst, basedir, confData)

    ret = tizenStudioInst.build_app_source(package=os.path.basename(sourceData.get('GIT_PATH')), \
                                           profile=sourceData.get('PROFILE'), \
                                           gitpath=sourceData.get('GIT_PATH'), \
                                           build_mode=confData.get('BUILD_MODE'), \
                                           parallel_jobs=parallel_jobs, \
                                           build_type='default')
    print '[ TizenStudio END ] %s' % (str(datetime.now()))
    print ret

    studioData = tizenStudioInst.gather_build_result()
    rs_ver = studioData.get('built_version')
    fail_title = studioData.get('title')
    fail_log = studioData.get('buildlog')
    ts_version = studioData.get('tizen_studio_version')
    ts_distribution = studioData.get('tizen_studio_distribution')
    if (rs_ver is None or rs_ver == ' ') and fail_title == 'FAIL::CLI PKG' and fail_log == '':
        print 'No rootstrap found for %s' % sourceData.get('PROFILE')
        fail_log = 'No rootstrap found for %s' % sourceData.get('PROFILE')
    print 'VM returned [%s] [%s] [%s] [%s] [%s]\n' % \
        (rs_ver, fail_title, fail_log, ts_version, ts_distribution)

    statusCode = 'PASS'

    if tizenStudioInst.build_result != 0 or fail_title != None:
         statusCode = 'FAIL'
         if option == 'check':
             with open('abs_build_result_code.env', 'w') as output_return:
                 output_return.write(statusCode)
             return
    else:
         if option == 'check':
             with open('abs_build_result_code.env', 'w') as output_return:
                 output_return.write(statusCode)
             return

         if ciData.get('BUILD_CAUSE') == 'GIT':
             postData = post_processing(tizenStudioInst, src_git, project_properties, \
                                        sourceData, confData, ciData, builddir)
             if postData.get('status') == 'FAIL':
                 statusCode = 'FAIL'
                 fail_title = 'Git push error'
                 fail_log   = postData.get('error')

    if statusCode == 'FAIL' and ciData.get('BUILD_CAUSE') == 'GIT':
        build_status_notification(statusCode, fail_title, fail_log, \
            sourceData.get('USER_EMAIL'), confData.get('ABS_MAILINGLIST').split(','), \
            mainProject=sourceData.get('PROJECT'), branch=sourceData.get('BRANCH'), \
            gitPath=sourceData.get('GIT_PATH'), packageName=sourceData.get('PACKAGE_NAME'), \
            tagName=sourceData.get('TAG_NAME'), rootstrapVersion=rs_ver)

    update_dashboard('START_ABS', ciData.get('BUILD_CAUSE'), \
                     statusCode, fail_title, \
                     sourceData, confData, ciData, studioData)

    with open('abs_build_result_code.env', 'w') as output_return:
        output_return.write(statusCode)

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

    return start_build(options)

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

