#
# Copyright OpenEmbedded Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#

import logging
import os
import sys
import shutil

import bb.utils

from bblayers.common import LayerPlugin

logger = logging.getLogger('bitbake-layers')

def plugin_init(plugins):
    return CreatePlugin()

def read_template(template, template_dir='templates'):
    lines = str()
    with open(os.path.join(os.path.dirname(__file__), template_dir, template)) as fd:
        lines = ''.join(fd.readlines())
    return lines

class CreatePlugin(LayerPlugin):
    def do_create_layer(self, args):
        """Create a basic layer"""
        layerdir = os.path.abspath(args.layerdir)
        if os.path.exists(layerdir):
            sys.stderr.write("Specified layer directory exists\n")
            return 1

        # create dirs
        conf = os.path.join(layerdir, 'conf')
        bb.utils.mkdirhier(conf)

        layername = os.path.basename(os.path.normpath(args.layerdir))
        layerid = args.layerid if args.layerid is not None else layername

        # Create the README from templates/README
        readme_template =  read_template('README').format(layername=layername)
        readme = os.path.join(layerdir, 'README')
        with open(readme, 'w') as fd:
            fd.write(readme_template)

        # Copy the MIT license from meta
        copying = 'COPYING.MIT'
        dn = os.path.dirname
        license_src = os.path.join(dn(dn(dn(__file__))), copying)
        license_dst = os.path.join(layerdir, copying)
        shutil.copy(license_src, license_dst)

        # Get the compat value for core layer.
        compat = self.tinfoil.config_data.getVar('LAYERSERIES_CORENAMES') or ""

        # Create the layer.conf from templates/layer.conf
        layerconf_template = read_template('layer.conf').format(
                layerid=layerid, priority=args.priority, compat=compat)
        layerconf = os.path.join(conf, 'layer.conf')
        with open(layerconf, 'w') as fd:
            fd.write(layerconf_template)

        # Create the example from templates/example.bb
        example_template = read_template('example.bb')
        example = os.path.join(layerdir, 'recipes-' + args.examplerecipe, args.examplerecipe)
        bb.utils.mkdirhier(example)
        with open(os.path.join(example, args.examplerecipe + '_%s.bb') % args.version, 'w') as fd:
            fd.write(example_template)

        logger.plain('Add your new layer with \'bitbake-layers add-layer %s\'' % args.layerdir)

    def register_commands(self, sp):
        parser_create_layer = self.add_command(sp, 'create-layer', self.do_create_layer, parserecipes=False)
        parser_create_layer.add_argument('layerdir', help='Layer directory to create')
        parser_create_layer.add_argument('--layerid', '-i', help='Layer id to use if different from layername')
        parser_create_layer.add_argument('--priority', '-p', default=6, help='Priority of recipes in layer')
        parser_create_layer.add_argument('--example-recipe-name', '-e', dest='examplerecipe', default='example', help='Filename of the example recipe')
        parser_create_layer.add_argument('--example-recipe-version', '-v', dest='version', default='0.1', help='Version number for the example recipe')

