# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (c) 2013, Intel Corporation.
# All rights reserved.
#
# 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.
#
# DESCRIPTION
# This module provides a place to collect various wic-related utils
# for the OpenEmbedded Image Tools.
#
# AUTHORS
# Tom Zanussi <tom.zanussi (at] linux.intel.com>
#
"""Miscellaneous functions."""

import os
from collections import defaultdict

from wic import msger
from wic.utils import runner

# executable -> recipe pairs for exec_native_cmd
NATIVE_RECIPES = {"mcopy": "mtools",
                  "mkdosfs": "dosfstools",
                  "mkfs.btrfs": "btrfs-tools",
                  "mkfs.ext2": "e2fsprogs",
                  "mkfs.ext3": "e2fsprogs",
                  "mkfs.ext4": "e2fsprogs",
                  "mkfs.vfat": "dosfstools",
                  "mksquashfs": "squashfs-tools",
                  "mkswap": "util-linux",
                  "parted": "parted",
                  "sgdisk": "gptfdisk",
                  "syslinux": "syslinux"
                 }

def _exec_cmd(cmd_and_args, as_shell=False, catch=3):
    """
    Execute command, catching stderr, stdout

    Need to execute as_shell if the command uses wildcards
    """
    msger.debug("_exec_cmd: %s" % cmd_and_args)
    args = cmd_and_args.split()
    msger.debug(args)

    if as_shell:
        ret, out = runner.runtool(cmd_and_args, catch)
    else:
        ret, out = runner.runtool(args, catch)
    out = out.strip()
    msger.debug("_exec_cmd: output for %s (rc = %d): %s" % \
                (cmd_and_args, ret, out))

    return (ret, out)


def exec_cmd(cmd_and_args, as_shell=False, catch=3):
    """
    Execute command, catching stderr, stdout

    Exits if rc non-zero
    """
    ret, out = _exec_cmd(cmd_and_args, as_shell, catch)

    if ret != 0:
        msger.error("exec_cmd: %s returned '%s' instead of 0" % \
                    (cmd_and_args, ret))

    return out

def cmd_in_path(cmd, path):
    import scriptpath

    scriptpath.add_bitbake_lib_path()

    return bb.utils.which(path, cmd) != "" or False

def exec_native_cmd(cmd_and_args, native_sysroot, catch=3):
    """
    Execute native command, catching stderr, stdout

    Need to execute as_shell if the command uses wildcards

    Always need to execute native commands as_shell
    """
    native_paths = \
        "%s/sbin:%s/usr/sbin:%s/usr/bin" % \
        (native_sysroot, native_sysroot, native_sysroot)
    native_cmd_and_args = "export PATH=%s:$PATH;%s" % \
                           (native_paths, cmd_and_args)
    msger.debug("exec_native_cmd: %s" % cmd_and_args)

    # The reason -1 is used is because there may be "export" commands.
    args = cmd_and_args.split(';')[-1].split()
    msger.debug(args)

    # If the command isn't in the native sysroot say we failed.
    if cmd_in_path(args[0], native_paths):
        ret, out = _exec_cmd(native_cmd_and_args, True, catch)
    else:
        ret = 127

    if ret == 127: # shell command-not-found
        prog = args[0]
        msg = "A native program %s required to build the image "\
              "was not found (see details above).\n\n" % prog
        recipe = NATIVE_RECIPES.get(prog)
        if recipe:
            msg += "Please bake it with 'bitbake %s-native' "\
                   "and try again.\n" % recipe
        else:
            msg += "Wic failed to find a recipe to build native %s. Please "\
                   "file a bug against wic.\n" % prog
        msger.error(msg)
    if out:
        msger.debug('"%s" output: %s' % (args[0], out))

    if ret != 0:
        msger.error("exec_cmd: '%s' returned '%s' instead of 0" % \
                    (cmd_and_args, ret))

    return ret, out

BOOTDD_EXTRA_SPACE = 16384

class BitbakeVars(defaultdict):
    """
    Container for Bitbake variables.
    """
    def __init__(self):
        defaultdict.__init__(self, dict)

        # default_image and vars_dir attributes should be set from outside
        self.default_image = None
        self.vars_dir = None

    def _parse_line(self, line, image):
        """
        Parse one line from bitbake -e output or from .env file.
        Put result key-value pair into the storage.
        """
        if "=" not in line:
            return
        try:
            key, val = line.split("=")
        except ValueError:
            return
        key = key.strip()
        val = val.strip()
        if key.replace('_', '').isalnum():
            self[image][key] = val.strip('"')

    def get_var(self, var, image=None):
        """
        Get bitbake variable from 'bitbake -e' output or from .env file.
        This is a lazy method, i.e. it runs bitbake or parses file only when
        only when variable is requested. It also caches results.
        """
        if not image:
            image = self.default_image

        if image not in self:
            if image and self.vars_dir:
                fname = os.path.join(self.vars_dir, image + '.env')
                if os.path.isfile(fname):
                    # parse .env file
                    with open(fname) as varsfile:
                        for line in varsfile:
                            self._parse_line(line, image)
                else:
                    print "Couldn't get bitbake variable from %s." % fname
                    print "File %s doesn't exist." % fname
                    return
            else:
                # Get bitbake -e output
                cmd = "bitbake -e"
                if image:
                    cmd += " %s" % image

                log_level = msger.get_loglevel()
                msger.set_loglevel('normal')
                ret, lines = _exec_cmd(cmd)
                msger.set_loglevel(log_level)

                if ret:
                    print "Couldn't get '%s' output." % cmd
                    print "Bitbake failed with error:\n%s\n" % lines
                    return

                # Parse bitbake -e output
                for line in lines.split('\n'):
                    self._parse_line(line, image)

            # Make first image a default set of variables
            images = [key for key in self if key]
            if len(images) == 1:
                self[None] = self[image]

        return self[image].get(var)

# Create BB_VARS singleton
BB_VARS = BitbakeVars()

def get_bitbake_var(var, image=None):
    """
    Provide old get_bitbake_var API by wrapping
    get_var method of BB_VARS singleton.
    """
    return BB_VARS.get_var(var, image)

def parse_sourceparams(sourceparams):
    """
    Split sourceparams string of the form key1=val1[,key2=val2,...]
    into a dict.  Also accepts valueless keys i.e. without =.

    Returns dict of param key/val pairs (note that val may be None).
    """
    params_dict = {}

    params = sourceparams.split(',')
    if params:
        for par in params:
            if not par:
                continue
            if not '=' in par:
                key = par
                val = None
            else:
                key, val = par.split('=')
            params_dict[key] = val

    return params_dict
