#!/usr/bin/env python3

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

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

# This can be removed once our minimum is Python 3.9: https://docs.python.org/3/whatsnew/3.9.html#type-hinting-generics-in-standard-collections
from typing import List


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')


class ConfigHandler:
    basepath = None
    config_file = ''
    config_obj = None
    init_path = ''
    workspace_path = ''

    def __init__(self, basepath, filename):
        self.basepath = basepath
        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 is not 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(self.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(self.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)


@dataclasses.dataclass
class Context:
    fixed_setup: bool
    config: ConfigHandler
    pluginpaths: List[str]


def read_workspace(basepath, context):
    workspace = {}
    if not os.path.exists(os.path.join(context.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' % context.config.workspace_path)
            _create_workspace(context.config.workspace_path, basepath)
    if not context.fixed_setup:
        _enable_workspace_layer(context.config.workspace_path, context.config, basepath)

    logger.debug('Reading workspace in %s' % context.config.workspace_path)
    externalsrc_re = re.compile(r'^EXTERNALSRC(:pn-([^ =]+))? *= *"([^"]*)"$')
    for fn in glob.glob(os.path.join(context.config.workspace_path, 'appends', '*.bbappend')):
        with open(fn, 'r') as f:
            pnvalues = {}
            pn = None
            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(context.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 pn:
                    raise DevtoolError("Found *.bbappend in %s, but could not determine EXTERNALSRC:pn-*. "
                            "Maybe still using old syntax?" % context.config.workspace_path)
                if not pnvalues.get('srctreebase', None):
                    pnvalues['srctreebase'] = pnvalues['srctree']
                logger.debug('Found recipe %s' % pnvalues)
                workspace[pn] = pnvalues

    return workspace

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'))
    layerseries = None
    if args.layerseries:
        layerseries = args.layerseries
    _create_workspace(workspacedir, basepath, layerseries)
    if not args.create_only:
        _enable_workspace_layer(workspacedir, config, basepath)

def _create_workspace(workspacedir, basepath, layerseries=None):
    import bb.utils

    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:
        if not layerseries:
            tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
            try:
                layerseries = tinfoil.config_data.getVar('LAYERSERIES_CORENAMES')
            finally:
                tinfoil.shutdown()

        # 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 = "%s"\n' % layerseries)
        # 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.utils
    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():
    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.")

    # 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)

    is_fixed_setup = False

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

        if not is_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(basepath, os.path.join(basepath, 'conf', 'devtool.conf'))
    if not config.read():
        return -1

    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:
        import bb
        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
    pluginpaths = [os.path.join(path, 'lib', 'devtool') for path in global_args.bbpath.split(':') + [scripts_path]]

    context = Context(fixed_setup=is_fixed_setup, config=config, pluginpaths=pluginpaths)

    plugins = []
    for pluginpath in pluginpaths:
        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('--layerseries', help='Layer series the workspace should be set to be compatible with')
        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)

    try:
        workspace = {}
        if not getattr(args, 'no_workspace', False):
            workspace = read_workspace(basepath, context)
        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)
        ret = 2

    return ret


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