#!/usr/bin/env python3

# OpenEmbedded Development tool
#
# Copyright (C) 2014-2015 Intel Corporation
#
# SPDX-License-Identifier: GPL-2.0-only
#

import sys
import os
import argparse
import glob
import re
import configparser
import subprocess
import logging

basepath = ''
workspace = {}
config = None
context = None


scripts_path = os.path.dirname(os.path.realpath(__file__))
lib_path = scripts_path + '/lib'
sys.path = sys.path + [lib_path]
from devtool import DevtoolError, setup_tinfoil
import scriptutils
import argparse_oe
logger = scriptutils.logger_create('devtool')

plugins = []


class ConfigHandler(object):
    config_file = ''
    config_obj = None
    init_path = ''
    workspace_path = ''

    def __init__(self, filename):
        self.config_file = filename
        self.config_obj = configparser.ConfigParser()

    def get(self, section, option, default=None):
        try:
            ret = self.config_obj.get(section, option)
        except (configparser.NoOptionError, configparser.NoSectionError):
            if default != None:
                ret = default
            else:
                raise
        return ret

    def read(self):
        if os.path.exists(self.config_file):
            self.config_obj.read(self.config_file)

            if self.config_obj.has_option('General', 'init_path'):
                pth = self.get('General', 'init_path')
                self.init_path = os.path.join(basepath, pth)
                if not os.path.exists(self.init_path):
                    logger.error('init_path %s specified in config file cannot be found' % pth)
                    return False
        else:
            self.config_obj.add_section('General')

        self.workspace_path = self.get('General', 'workspace_path', os.path.join(basepath, 'workspace'))
        return True


    def write(self):
        logger.debug('writing to config file %s' % self.config_file)
        self.config_obj.set('General', 'workspace_path', self.workspace_path)
        with open(self.config_file, 'w') as f:
            self.config_obj.write(f)

    def set(self, section, option, value):
        if not self.config_obj.has_section(section):
            self.config_obj.add_section(section)
        self.config_obj.set(section, option, value)

class Context:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)


def read_workspace():
    global workspace
    workspace = {}
    if not os.path.exists(os.path.join(config.workspace_path, 'conf', 'layer.conf')):
        if context.fixed_setup:
            logger.error("workspace layer not set up")
            sys.exit(1)
        else:
            logger.info('Creating workspace layer in %s' % config.workspace_path)
            _create_workspace(config.workspace_path, config, basepath)
    if not context.fixed_setup:
        _enable_workspace_layer(config.workspace_path, config, basepath)

    logger.debug('Reading workspace in %s' % config.workspace_path)
    externalsrc_re = re.compile(r'^EXTERNALSRC(:pn-([^ =]+))? *= *"([^"]*)"$')
    for fn in glob.glob(os.path.join(config.workspace_path, 'appends', '*.bbappend')):
        with open(fn, 'r') as f:
            pnvalues = {}
            for line in f:
                res = externalsrc_re.match(line.rstrip())
                if res:
                    recipepn = os.path.splitext(os.path.basename(fn))[0].split('_')[0]
                    pn = res.group(2) or recipepn
                    # Find the recipe file within the workspace, if any
                    bbfile = os.path.basename(fn).replace('.bbappend', '.bb').replace('%', '*')
                    recipefile = glob.glob(os.path.join(config.workspace_path,
                                                        'recipes',
                                                        recipepn,
                                                        bbfile))
                    if recipefile:
                        recipefile = recipefile[0]
                    pnvalues['srctree'] = res.group(3)
                    pnvalues['bbappend'] = fn
                    pnvalues['recipefile'] = recipefile
                elif line.startswith('# srctreebase: '):
                    pnvalues['srctreebase'] = line.split(':', 1)[1].strip()
            if pnvalues:
                if not pnvalues.get('srctreebase', None):
                    pnvalues['srctreebase'] = pnvalues['srctree']
                logger.debug('Found recipe %s' % pnvalues)
                workspace[pn] = pnvalues

def create_workspace(args, config, basepath, workspace):
    if args.layerpath:
        workspacedir = os.path.abspath(args.layerpath)
    else:
        workspacedir = os.path.abspath(os.path.join(basepath, 'workspace'))
    _create_workspace(workspacedir, config, basepath)
    if not args.create_only:
        _enable_workspace_layer(workspacedir, config, basepath)

def _create_workspace(workspacedir, config, basepath):
    import bb

    confdir = os.path.join(workspacedir, 'conf')
    if os.path.exists(os.path.join(confdir, 'layer.conf')):
        logger.info('Specified workspace already set up, leaving as-is')
    else:
        # Add a config file
        bb.utils.mkdirhier(confdir)
        with open(os.path.join(confdir, 'layer.conf'), 'w') as f:
            f.write('# ### workspace layer auto-generated by devtool ###\n')
            f.write('BBPATH =. "$' + '{LAYERDIR}:"\n')
            f.write('BBFILES += "$' + '{LAYERDIR}/recipes/*/*.bb \\\n')
            f.write('            $' + '{LAYERDIR}/appends/*.bbappend"\n')
            f.write('BBFILE_COLLECTIONS += "workspacelayer"\n')
            f.write('BBFILE_PATTERN_workspacelayer = "^$' + '{LAYERDIR}/"\n')
            f.write('BBFILE_PATTERN_IGNORE_EMPTY_workspacelayer = "1"\n')
            f.write('BBFILE_PRIORITY_workspacelayer = "99"\n')
            f.write('LAYERSERIES_COMPAT_workspacelayer = "${LAYERSERIES_COMPAT_core}"\n')
        # Add a README file
        with open(os.path.join(workspacedir, 'README'), 'w') as f:
            f.write('This layer was created by the OpenEmbedded devtool utility in order to\n')
            f.write('contain recipes and bbappends that are currently being worked on. The idea\n')
            f.write('is that the contents is temporary - once you have finished working on a\n')
            f.write('recipe you use the appropriate method to move the files you have been\n')
            f.write('working on to a proper layer. In most instances you should use the\n')
            f.write('devtool utility to manage files within it rather than modifying files\n')
            f.write('directly (although recipes added with "devtool add" will often need\n')
            f.write('direct modification.)\n')
            f.write('\nIf you no longer need to use devtool or the workspace layer\'s contents\n')
            f.write('you can remove the path to this workspace layer from your conf/bblayers.conf\n')
            f.write('file (and then delete the layer, if you wish).\n')
            f.write('\nNote that by default, if devtool fetches and unpacks source code, it\n')
            f.write('will place it in a subdirectory of a "sources" subdirectory of the\n')
            f.write('layer. If you prefer it to be elsewhere you can specify the source\n')
            f.write('tree path on the command line.\n')

def _enable_workspace_layer(workspacedir, config, basepath):
    """Ensure the workspace layer is in bblayers.conf"""
    import bb
    bblayers_conf = os.path.join(basepath, 'conf', 'bblayers.conf')
    if not os.path.exists(bblayers_conf):
        logger.error('Unable to find bblayers.conf')
        return
    if os.path.abspath(workspacedir) != os.path.abspath(config.workspace_path):
        removedir = config.workspace_path
    else:
        removedir = None
    _, added = bb.utils.edit_bblayers_conf(bblayers_conf, workspacedir, removedir)
    if added:
        logger.info('Enabling workspace layer in bblayers.conf')
    if config.workspace_path != workspacedir:
        # Update our config to point to the new location
        config.workspace_path = workspacedir
        config.write()


def main():
    global basepath
    global config
    global context

    if sys.getfilesystemencoding() != "utf-8":
        sys.exit("Please use a locale setting which supports utf-8.\nPython can't change the filesystem locale after loading so we need a utf-8 when python starts or things won't work.")

    context = Context(fixed_setup=False)

    # Default basepath
    basepath = os.path.dirname(os.path.abspath(__file__))

    parser = argparse_oe.ArgumentParser(description="OpenEmbedded development tool",
                                        add_help=False,
                                        epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
    parser.add_argument('--basepath', help='Base directory of SDK / build directory')
    parser.add_argument('--bbpath', help='Explicitly specify the BBPATH, rather than getting it from the metadata')
    parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
    parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
    parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')

    global_args, unparsed_args = parser.parse_known_args()

    # Help is added here rather than via add_help=True, as we don't want it to
    # be handled by parse_known_args()
    parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
                        help='show this help message and exit')

    if global_args.debug:
        logger.setLevel(logging.DEBUG)
    elif global_args.quiet:
        logger.setLevel(logging.ERROR)

    if global_args.basepath:
        # Override
        basepath = global_args.basepath
        if os.path.exists(os.path.join(basepath, '.devtoolbase')):
            context.fixed_setup = True
    else:
        pth = basepath
        while pth != '' and pth != os.sep:
            if os.path.exists(os.path.join(pth, '.devtoolbase')):
                context.fixed_setup = True
                basepath = pth
                break
            pth = os.path.dirname(pth)

        if not context.fixed_setup:
            basepath = os.environ.get('BUILDDIR')
            if not basepath:
                logger.error("This script can only be run after initialising the build environment (e.g. by using oe-init-build-env)")
                sys.exit(1)

    logger.debug('Using basepath %s' % basepath)

    config = ConfigHandler(os.path.join(basepath, 'conf', 'devtool.conf'))
    if not config.read():
        return -1
    context.config = config

    bitbake_subdir = config.get('General', 'bitbake_subdir', '')
    if bitbake_subdir:
        # Normally set for use within the SDK
        logger.debug('Using bitbake subdir %s' % bitbake_subdir)
        sys.path.insert(0, os.path.join(basepath, bitbake_subdir, 'lib'))
        core_meta_subdir = config.get('General', 'core_meta_subdir')
        sys.path.insert(0, os.path.join(basepath, core_meta_subdir, 'lib'))
    else:
        # Standard location
        import scriptpath
        bitbakepath = scriptpath.add_bitbake_lib_path()
        if not bitbakepath:
            logger.error("Unable to find bitbake by searching parent directory of this script or PATH")
            sys.exit(1)
        logger.debug('Using standard bitbake path %s' % bitbakepath)
        scriptpath.add_oe_lib_path()

    scriptutils.logger_setup_color(logger, global_args.color)

    if global_args.bbpath is None:
        try:
            tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
            try:
                global_args.bbpath = tinfoil.config_data.getVar('BBPATH')
            finally:
                tinfoil.shutdown()
        except bb.BBHandledException:
            return 2

    # Search BBPATH first to allow layers to override plugins in scripts_path
    for path in global_args.bbpath.split(':') + [scripts_path]:
        pluginpath = os.path.join(path, 'lib', 'devtool')
        scriptutils.load_plugins(logger, plugins, pluginpath)

    subparsers = parser.add_subparsers(dest="subparser_name", title='subcommands', metavar='<subcommand>')
    subparsers.required = True

    subparsers.add_subparser_group('sdk', 'SDK maintenance', -2)
    subparsers.add_subparser_group('advanced', 'Advanced', -1)
    subparsers.add_subparser_group('starting', 'Beginning work on a recipe', 100)
    subparsers.add_subparser_group('info', 'Getting information')
    subparsers.add_subparser_group('working', 'Working on a recipe in the workspace')
    subparsers.add_subparser_group('testbuild', 'Testing changes on target')

    if not context.fixed_setup:
        parser_create_workspace = subparsers.add_parser('create-workspace',
                                                        help='Set up workspace in an alternative location',
                                                        description='Sets up a new workspace. NOTE: other devtool subcommands will create a workspace automatically as needed, so you only need to use %(prog)s if you want to specify where the workspace should be located.',
                                                        group='advanced')
        parser_create_workspace.add_argument('layerpath', nargs='?', help='Path in which the workspace layer should be created')
        parser_create_workspace.add_argument('--create-only', action="store_true", help='Only create the workspace layer, do not alter configuration')
        parser_create_workspace.set_defaults(func=create_workspace, no_workspace=True)

    for plugin in plugins:
        if hasattr(plugin, 'register_commands'):
            plugin.register_commands(subparsers, context)

    args = parser.parse_args(unparsed_args, namespace=global_args)

    if not getattr(args, 'no_workspace', False):
        read_workspace()

    try:
        ret = args.func(args, config, basepath, workspace)
    except DevtoolError as err:
        if str(err):
            logger.error(str(err))
        ret = err.exitcode
    except argparse_oe.ArgumentUsageError as ae:
        parser.error_subcommand(ae.message, ae.subcommand)

    return ret


if __name__ == "__main__":
    try:
        ret = main()
    except Exception:
        ret = 1
        import traceback
        traceback.print_exc()
    sys.exit(ret)
