#!/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_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

    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)
