# Development tool - sdk-update command plugin
#
# Copyright (C) 2015-2016 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# 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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import os
import subprocess
import logging
import glob
import shutil
import errno
import sys
import tempfile
import re
from devtool import exec_build_env_command, setup_tinfoil, parse_recipe, DevtoolError

logger = logging.getLogger('devtool')

def parse_locked_sigs(sigfile_path):
    """Return <pn:task>:<hash> dictionary"""
    sig_dict = {}
    with open(sigfile_path) as f:
        lines = f.readlines()
        for line in lines:
            if ':' in line:
                taskkey, _, hashval = line.rpartition(':')
                sig_dict[taskkey.strip()] = hashval.split()[0]
    return sig_dict

def generate_update_dict(sigfile_new, sigfile_old):
    """Return a dict containing <pn:task>:<hash> which indicates what need to be updated"""
    update_dict = {}
    sigdict_new = parse_locked_sigs(sigfile_new)
    sigdict_old = parse_locked_sigs(sigfile_old)
    for k in sigdict_new:
        if k not in sigdict_old:
            update_dict[k] = sigdict_new[k]
            continue
        if sigdict_new[k] != sigdict_old[k]:
            update_dict[k] = sigdict_new[k]
            continue
    return update_dict

def get_sstate_objects(update_dict, sstate_dir):
    """Return a list containing sstate objects which are to be installed"""
    sstate_objects = []
    for k in update_dict:
        files = set()
        hashval = update_dict[k]
        p = sstate_dir + '/' + hashval[:2] + '/*' + hashval + '*.tgz'
        files |= set(glob.glob(p))
        p = sstate_dir + '/*/' + hashval[:2] + '/*' + hashval + '*.tgz'
        files |= set(glob.glob(p))
        files = list(files)
        if len(files) == 1:
            sstate_objects.extend(files)
        elif len(files) > 1:
            logger.error("More than one matching sstate object found for %s" % hashval)

    return sstate_objects

def mkdir(d):
    try:
        os.makedirs(d)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise e

def install_sstate_objects(sstate_objects, src_sdk, dest_sdk):
    """Install sstate objects into destination SDK"""
    sstate_dir = os.path.join(dest_sdk, 'sstate-cache')
    if not os.path.exists(sstate_dir):
        logger.error("Missing sstate-cache directory in %s, it might not be an extensible SDK." % dest_sdk)
        raise
    for sb in sstate_objects:
        dst = sb.replace(src_sdk, dest_sdk)
        destdir = os.path.dirname(dst)
        mkdir(destdir)
        logger.debug("Copying %s to %s" % (sb, dst))
        shutil.copy(sb, dst)

def check_manifest(fn, basepath):
    import bb.utils
    changedfiles = []
    with open(fn, 'r') as f:
        for line in f:
            splitline = line.split()
            if len(splitline) > 1:
                chksum = splitline[0]
                fpath = splitline[1]
                curr_chksum = bb.utils.sha256_file(os.path.join(basepath, fpath))
                if chksum != curr_chksum:
                    logger.debug('File %s changed: old csum = %s, new = %s' % (os.path.join(basepath, fpath), curr_chksum, chksum))
                    changedfiles.append(fpath)
    return changedfiles

def sdk_update(args, config, basepath, workspace):
    """Entry point for devtool sdk-update command"""
    updateserver = args.updateserver
    if not updateserver:
        updateserver = config.get('SDK', 'updateserver', '')
    logger.debug("updateserver: %s" % updateserver)

    # Make sure we are using sdk-update from within SDK
    logger.debug("basepath = %s" % basepath)
    old_locked_sig_file_path = os.path.join(basepath, 'conf/locked-sigs.inc')
    if not os.path.exists(old_locked_sig_file_path):
        logger.error("Not using devtool's sdk-update command from within an extensible SDK. Please specify correct basepath via --basepath option")
        return -1
    else:
        logger.debug("Found conf/locked-sigs.inc in %s" % basepath)

    if not '://' in updateserver:
        logger.error("Update server must be a URL")
        return -1

    layers_dir = os.path.join(basepath, 'layers')
    conf_dir = os.path.join(basepath, 'conf')

    # Grab variable values
    tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
    try:
        stamps_dir = tinfoil.config_data.getVar('STAMPS_DIR')
        sstate_mirrors = tinfoil.config_data.getVar('SSTATE_MIRRORS')
        site_conf_version = tinfoil.config_data.getVar('SITE_CONF_VERSION')
    finally:
        tinfoil.shutdown()

    tmpsdk_dir = tempfile.mkdtemp()
    try:
        os.makedirs(os.path.join(tmpsdk_dir, 'conf'))
        new_locked_sig_file_path = os.path.join(tmpsdk_dir, 'conf', 'locked-sigs.inc')
        # Fetch manifest from server
        tmpmanifest = os.path.join(tmpsdk_dir, 'conf', 'sdk-conf-manifest')
        ret = subprocess.call("wget -q -O %s %s/conf/sdk-conf-manifest" % (tmpmanifest, updateserver), shell=True)
        changedfiles = check_manifest(tmpmanifest, basepath)
        if not changedfiles:
            logger.info("Already up-to-date")
            return 0
        # Update metadata
        logger.debug("Updating metadata via git ...")
        #Check for the status before doing a fetch and reset
        if os.path.exists(os.path.join(basepath, 'layers/.git')):
            out = subprocess.check_output("git status --porcelain", shell=True, cwd=layers_dir)
            if not out:
                ret = subprocess.call("git fetch --all; git reset --hard @{u}", shell=True, cwd=layers_dir)
            else:
                logger.error("Failed to update metadata as there have been changes made to it. Aborting.");
                logger.error("Changed files:\n%s" % out);
                return -1
        else:
            ret = -1
        if ret != 0:
            ret = subprocess.call("git clone %s/layers/.git" % updateserver, shell=True, cwd=tmpsdk_dir)
            if ret != 0:
                logger.error("Updating metadata via git failed")
                return ret
        logger.debug("Updating conf files ...")
        for changedfile in changedfiles:
            ret = subprocess.call("wget -q -O %s %s/%s" % (changedfile, updateserver, changedfile), shell=True, cwd=tmpsdk_dir)
            if ret != 0:
                logger.error("Updating %s failed" % changedfile)
                return ret

        # Check if UNINATIVE_CHECKSUM changed
        uninative = False
        if 'conf/local.conf' in changedfiles:
            def read_uninative_checksums(fn):
                chksumitems = []
                with open(fn, 'r') as f:
                    for line in f:
                        if line.startswith('UNINATIVE_CHECKSUM'):
                            splitline = re.split(r'[\[\]"\']', line)
                            if len(splitline) > 3:
                                chksumitems.append((splitline[1], splitline[3]))
                return chksumitems

            oldsums = read_uninative_checksums(os.path.join(basepath, 'conf/local.conf'))
            newsums = read_uninative_checksums(os.path.join(tmpsdk_dir, 'conf/local.conf'))
            if oldsums != newsums:
                uninative = True
                for buildarch, chksum in newsums:
                    uninative_file = os.path.join('downloads', 'uninative', chksum, '%s-nativesdk-libc.tar.bz2' % buildarch)
                    mkdir(os.path.join(tmpsdk_dir, os.path.dirname(uninative_file)))
                    ret = subprocess.call("wget -q -O %s %s/%s" % (uninative_file, updateserver, uninative_file), shell=True, cwd=tmpsdk_dir)

        # Ok, all is well at this point - move everything over
        tmplayers_dir = os.path.join(tmpsdk_dir, 'layers')
        if os.path.exists(tmplayers_dir):
            shutil.rmtree(layers_dir)
            shutil.move(tmplayers_dir, layers_dir)
        for changedfile in changedfiles:
            destfile = os.path.join(basepath, changedfile)
            os.remove(destfile)
            shutil.move(os.path.join(tmpsdk_dir, changedfile), destfile)
        os.remove(os.path.join(conf_dir, 'sdk-conf-manifest'))
        shutil.move(tmpmanifest, conf_dir)
        if uninative:
            shutil.rmtree(os.path.join(basepath, 'downloads', 'uninative'))
            shutil.move(os.path.join(tmpsdk_dir, 'downloads', 'uninative'), os.path.join(basepath, 'downloads'))

        if not sstate_mirrors:
            with open(os.path.join(conf_dir, 'site.conf'), 'a') as f:
                f.write('SCONF_VERSION = "%s"\n' % site_conf_version)
                f.write('SSTATE_MIRRORS_append = " file://.* %s/sstate-cache/PATH \\n "\n' % updateserver)
    finally:
        shutil.rmtree(tmpsdk_dir)

    if not args.skip_prepare:
        # Find all potentially updateable tasks
        sdk_update_targets = []
        tasks = ['do_populate_sysroot', 'do_packagedata']
        for root, _, files in os.walk(stamps_dir):
            for fn in files:
                if not '.sigdata.' in fn:
                    for task in tasks:
                        if '.%s.' % task in fn or '.%s_setscene.' % task in fn:
                            sdk_update_targets.append('%s:%s' % (os.path.basename(root), task))
        # Run bitbake command for the whole SDK
        logger.info("Preparing build system... (This may take some time.)")
        try:
            exec_build_env_command(config.init_path, basepath, 'bitbake --setscene-only %s' % ' '.join(sdk_update_targets), stderr=subprocess.STDOUT)
            output, _ = exec_build_env_command(config.init_path, basepath, 'bitbake -n %s' % ' '.join(sdk_update_targets), stderr=subprocess.STDOUT)
            runlines = []
            for line in output.splitlines():
                if 'Running task ' in line:
                    runlines.append(line)
            if runlines:
                logger.error('Unexecuted tasks found in preparation log:\n  %s' % '\n  '.join(runlines))
                return -1
        except bb.process.ExecutionError as e:
            logger.error('Preparation failed:\n%s' % e.stdout)
            return -1
    return 0

def sdk_install(args, config, basepath, workspace):
    """Entry point for the devtool sdk-install command"""

    import oe.recipeutils
    import bb.process

    for recipe in args.recipename:
        if recipe in workspace:
            raise DevtoolError('recipe %s is a recipe in your workspace' % recipe)

    tasks = ['do_populate_sysroot', 'do_packagedata']
    stampprefixes = {}
    def checkstamp(recipe):
        stampprefix = stampprefixes[recipe]
        stamps = glob.glob(stampprefix + '*')
        for stamp in stamps:
            if '.sigdata.' not in stamp and stamp.startswith((stampprefix + '.', stampprefix + '_setscene.')):
                return True
        else:
            return False

    install_recipes = []
    tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
    try:
        for recipe in args.recipename:
            rd = parse_recipe(config, tinfoil, recipe, True)
            if not rd:
                return 1
            stampprefixes[recipe] = '%s.%s' % (rd.getVar('STAMP'), tasks[0])
            if checkstamp(recipe):
                logger.info('%s is already installed' % recipe)
            else:
                install_recipes.append(recipe)
    finally:
        tinfoil.shutdown()

    if install_recipes:
        logger.info('Installing %s...' % ', '.join(install_recipes))
        install_tasks = []
        for recipe in install_recipes:
            for task in tasks:
                if recipe.endswith('-native') and 'package' in task:
                    continue
                install_tasks.append('%s:%s' % (recipe, task))
        options = ''
        if not args.allow_build:
            options += ' --setscene-only'
        try:
            exec_build_env_command(config.init_path, basepath, 'bitbake %s %s' % (options, ' '.join(install_tasks)), watch=True)
        except bb.process.ExecutionError as e:
            raise DevtoolError('Failed to install %s:\n%s' % (recipe, str(e)))
        failed = False
        for recipe in install_recipes:
            if checkstamp(recipe):
                logger.info('Successfully installed %s' % recipe)
            else:
                raise DevtoolError('Failed to install %s - unavailable' % recipe)
                failed = True
        if failed:
            return 2

        try:
            exec_build_env_command(config.init_path, basepath, 'bitbake build-sysroots', watch=True)
        except bb.process.ExecutionError as e:
            raise DevtoolError('Failed to bitbake build-sysroots:\n%s' % (str(e)))


def register_commands(subparsers, context):
    """Register devtool subcommands from the sdk plugin"""
    if context.fixed_setup:
        parser_sdk = subparsers.add_parser('sdk-update',
                                           help='Update SDK components',
                                           description='Updates installed SDK components from a remote server',
                                           group='sdk')
        updateserver = context.config.get('SDK', 'updateserver', '')
        if updateserver:
            parser_sdk.add_argument('updateserver', help='The update server to fetch latest SDK components from (default %s)' % updateserver, nargs='?')
        else:
            parser_sdk.add_argument('updateserver', help='The update server to fetch latest SDK components from')
        parser_sdk.add_argument('--skip-prepare', action="store_true", help='Skip re-preparing the build system after updating (for debugging only)')
        parser_sdk.set_defaults(func=sdk_update)

        parser_sdk_install = subparsers.add_parser('sdk-install',
                                                   help='Install additional SDK components',
                                                   description='Installs additional recipe development files into the SDK. (You can use "devtool search" to find available recipes.)',
                                                   group='sdk')
        parser_sdk_install.add_argument('recipename', help='Name of the recipe to install the development artifacts for', nargs='+')
        parser_sdk_install.add_argument('-s', '--allow-build', help='Allow building requested item(s) from source', action='store_true')
        parser_sdk_install.set_defaults(func=sdk_install)
