#!/usr/bin/env python3

# OpenEmbedded Development tool
#
# Copyright (C) 2014-2015 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 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.SafeConfigParser()

    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:
            for line in f:
                res = externalsrc_re.match(line.rstrip())
                if res:
                    pn = res.group(2) or os.path.splitext(os.path.basename(fn))[0].split('_')[0]
                    # 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',
                                                        pn,
                                                        bbfile))
                    if recipefile:
                        recipefile = recipefile[0]
                    workspace[pn] = {'srctree': res.group(3),
                                     'bbappend': fn,
                                     'recipefile': recipefile}
                    logger.debug('Found recipe %s' % workspace[pn])

def create_unlockedsigs():
    """ This function will make unlocked-sigs.inc match the recipes in the
    workspace. This runs on every run of devtool, but it lets us ensure
    the unlocked items are in sync with the workspace. """

    confdir = os.path.join(basepath, 'conf')
    unlockedsigs = os.path.join(confdir, 'unlocked-sigs.inc')
    bb.utils.mkdirhier(confdir)
    with open(os.path.join(confdir, 'unlocked-sigs.inc'), 'w') as f:
        f.write("# DO NOT MODIFY! YOUR CHANGES WILL BE LOST.\n" +
                "# This layer was created by the OpenEmbedded devtool" +
                " utility in order to\n" +
                "# contain recipes that are unlocked.\n")

        f.write('SIGGEN_UNLOCKED_RECIPES += "\\\n')
        for pn in workspace:
            f.write('    ' + pn)
        f.write('"')

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')
        # 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
    _, added = bb.utils.edit_bblayers_conf(bblayers_conf, workspacedir, config.workspace_path)
    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

    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:
        tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
        try:
            global_args.bbpath = tinfoil.config_data.getVar('BBPATH', True)
        finally:
            tinfoil.shutdown()

    for path in [scripts_path] + global_args.bbpath.split(':'):
        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()
        create_unlockedsigs()

    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)
