#!/usr/bin/python

# Copyright (C) 2010 Intel Inc.  All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or version 3 (at your option).

import sys
import mic.cmdln as cmdln
import optparse as _optparse
import subprocess

try:
    import mic.__version__
    version = mic.__version__.version
except:
    version = 'unknown'

MAN_HEADER = r""".TH %(ucname)s "1" "%(date)s" "%(name)s %(version)s" "User Commands"
.SH NAME
%(name)s \- MeeGo image command-line tool.
.SH SYNOPSIS
.B %(name)s
[\fIGLOBALOPTS\fR] \fISUBCOMMAND \fR[\fIOPTS\fR] [\fIARGS\fR...]
.br
.B %(name)s
\fIhelp SUBCOMMAND\fR
.SH DESCRIPTION
MeeGo image command-line tool.
"""
MAN_FOOTER = r"""
.SH "SEE ALSO"
Type 'mic help <subcommand>' for more detailed help on a specific subcommand.
.PP
For additional information, see
 * http://www.meego.com/
 * http://moblin.org/projects/moblin-image-creator-2
.SH AUTHOR
mic was written by Yi Yang, Anas Nashif and Jianfeng Ding. This man page is automatically generated.
"""

class MIC(cmdln.Cmdln):
    """Usage: mic [GLOBALOPTS] SUBCOMMAND [OPTS] [ARGS...]
    or: mic help SUBCOMMAND

    MeeGo Image Tool.
    Type 'mic help <subcommand>' for help on a specific subcommand.

    ${command_list}
    ${help_list}
    global ${option_list}
    For additional information, see
    * http://www.meego.com/
    """
    name = 'mic'
    conf = None
    man_header = MAN_HEADER
    man_footer = MAN_FOOTER

    def run_subcmd(self, subcmd, opts, args):
        creator = "mic-image-creator"
        convertor = "mic-image-convertor"
        chroot = "mic-chroot"
        writer = "mic-image-writer"
        vmlauncher = "mic-vm-launcher"
        tools = {
                 "cr":creator, "create":creator,
                 "cv":convertor, "convert":convertor,
                 "ch":chroot, "chroot":chroot,
                 "wr":writer, "write":writer,
                 "lv":vmlauncher, "launchvm":vmlauncher
                }

        changed_opts = {"overlaysizemb":"overlay-size-mb", "cachedir":"cache", "srcimg":"source-image", "dstformat":"target-format",
                        "srcformat":"source-format", "convertto":"convert-to", "give_shell":"shell", "saveto":"save-to",
                        "unpackonly":"unpack-only", "convertonly":"convert-only", "buildbootstrap":"build-bootstrap",
                        "bindmounts":"bind-mounts", "use_comps":"use-comps", "run_mode":"run-mode", "save_kernel":"save-kernel",
                        "file":"logfile", "include_src":"include-source"
                       }

        argv = [tools[subcmd]]
        for key in opts.__dict__.keys():
            if key == "addrepos":
                addrepos = getattr(opts, key)
                if not addrepos:
                    continue
                for repo in getattr(opts, key):
                    optstr = "--repo=%s" % repo
                    argv.append(optstr)
                continue
            value = getattr(opts, key)
            if value == None or (type(value) is bool and value == False) or value == "":
                continue
            optstr = "--%s" % key.replace("_", "-")
            if key in changed_opts.keys():
                optstr = "--%s" % changed_opts[key]
            if type(value) is not bool:
                optstr += "=%s" % value
            argv.append(optstr)
        for arg in args:
            argv.append(arg)
        subprocess.call(argv)

    def get_version(self):
        return version

    def get_optparser(self):
        """this is the parser for "global" options (not specific to subcommand)"""

        optparser = cmdln.CmdlnOptionParser(self, version=version)
        return optparser



    def get_cmd_help(self, cmdname):
        doc = self._get_cmd_handler(cmdname).__doc__
        doc = self._help_reindent(doc)
        doc = self._help_preprocess(doc, cmdname)
        doc = doc.rstrip() + '\n' # trim down trailing space
        return self._str(doc)


    """ For mic-image-creator """
    @cmdln.alias('cr')
    @cmdln.option("-c", "--config", type="string", dest="config",
                    help="Path to kickstart config file")

    @cmdln.option("-f", "--format", type="string", dest="format",
                    help="Image format, you can specify as fs, livecd, liveusb, loop, raw, nand, mrstnand, ubi, jffs2, vdi or vmdk")

    @cmdln.option("-t", "--tmpdir", type="string",
                      dest="tmpdir",
                      help="Temporary directory to use (default: /var/tmp)")
    @cmdln.option("-k", "--cache", type="string",
                      dest="cachedir", default=None,
                      help="Cache directory to use (default: private cache)")
    @cmdln.option("-o", "--outdir", type="string",
                      dest="outdir", default=None,
                      help="Output directory to use (default: current work dir)")
    @cmdln.option("", "--release", type="string",
                      dest="release", default=None,
                      help="Generate a MeeGo release with all necessary files for publishing.")
    @cmdln.option("", "--genchecksum", action="store_true",
                      dest="genchecksum", default=False,
                      help="Generate checksum for image file if this option is provided")
    @cmdln.option("-P", "--prefix", type="string",
                      dest="prefix", default=None,
                      help="Image name prefix (default: meego)")
    @cmdln.option("-S", "--suffix", type="string",
                      dest="suffix", default=None,
                      help="Image name suffix (default: date stamp)")
    @cmdln.option("-b", "--build-bootstrap", action="store_true",
                      dest="buildbootstrap", default=False,
                      help="Build a bootstrap, it should be used with -B or --bootstrap together")
    @cmdln.option("", "--mainrepo", type="string",
                      dest="mainrepo", default=None,
                      help="Specify main repo name, it must be a repo name in your kickstart file")
    @cmdln.option("", "--siteconf", type="string", action="store",
                      dest="siteconf",
                      help="Specify site config file, it can be used to set tmpdir, cachedir, outputdir, it also can be used to remap/reroute a repo in kickstart to another equivalent repo, the default site configs are /etc/mic2/mic2.conf and ~/.mic2.conf.")
    @cmdln.option("", "--ignore-siteconf", action="store_true",
                      dest="ignore_siteconf", default=False,
                      help="Ignore site configs, this will ignore the default site configs, also ignore --siteconf option.")
    @cmdln.option("", "--repo", type="string", action="append", metavar="REPO",
                      dest="addrepos",
                      help="Specify additional repo, it may be a simple URL or a complicated tuple string, you can specify multiple repos using this option multiple times")
    @cmdln.option("", "--default-ks", type="string",
                      help="Set which kickstart file from repos to select in advance, if specified, there isn't interaction needed any more.")
    @cmdln.option("-B", "--bootstrap", type="string",
                      dest="bootstrap", default=None,
                      help="Use a given bootstrap env to create image")
    @cmdln.option("-a", "--arch", type="string",
                      dest="arch", default=None,
                      help="Specify target arch of image, for example: arm")
    @cmdln.option("", "--use-comps", action="store_true",
                      dest="use_comps", default=False,
                      help="Use comps instead of patterns if comps exists")
    @cmdln.option("", "--run-mode", type="int",
                      dest="run_mode", default=-1,
                      help="Specify run mode, 0 means legacy, 1 means bootstrap, by default it is gotten from config file.")
    @cmdln.option("", "--alt-initrd-name", type="string",
                      dest="alt_initrd_name", default=None,
                      help="Name of alternate initrd image, if NOT to use the one from kernel package")
    @cmdln.option("", "--record-pkgs", type="string",
                      dest="record_pkgs", default=None,
                      help="Record the installed packages, valid values: name, content")
    @cmdln.option("", "--local-pkgs-path", type="string",
                      dest="local_pkgs_path", default=None,
                      help="Path for local pkgs (rpms) to be installed")
    @cmdln.option("-p", "--package", type="string", dest="package", default="none",
                      help="Package format, this option will package up output into a given-format package, "
                           "currently only tar, tar.gz and tar.bz2 are supported, the default "
                           "is none, i.e. doesn't package up output")
    @cmdln.option("", "--compress-disk-image", type="string",
                      dest="compress_disk_image", default=None,
                      help="Compress the disk image that is created. When using --release option default is bz2,"
                           " otherwise default is none. Supported compression methods: bz2, none")
    @cmdln.option("", "--include-source", action="store_true",
                      dest="include_src", default=False,
                      help="Generate a image with source rpms included")

    @cmdln.option("-i", "--interactive", action="store_true",
                      dest="interactive", default=False,
                      help="Directly write into a USB disk.")
    @cmdln.option("", "--fstype", type="string",
                      dest="fstype", default="vfat",
                      help="File system type for live USB file image, ext3 or vfat, the default is vfat.")
    @cmdln.option("", "--overlay-size-mb", type="int", default=64,
                      help="Overlay size in MB as unit, it means how size changes you can save in your live USB disk.")

    @cmdln.option("", "--initrd-url", type="string",
                      dest="initrd_url", default=None,
                      help="URL of initrd.img, if it need to be retrieved from remote site.")
    @cmdln.option("", "--initrd-path", type="string",
                      dest="initrd_path", default=None,
                      help="Path of initrd.img, if it was saved in local filesystem.")
    @cmdln.option("", "--kernel-url", type="string",
                      dest="kernel_url", default=None,
                      help="URL of kernel file(vmlinuz), if it need to be retrieved from remote site.")
    @cmdln.option("", "--kernel-path", type="string",
                      dest="kernel_path", default=None,
                      help="Path of kernel file(vmlinuz), if it was saved in local filesystem.")
    @cmdln.option("", "--kernel-rpm-url", type="string",
                      dest="kernel_rpm_url", default=None,
                      help="URL of kernel rpm package, if it need to be retrieved from remote site.")
    @cmdln.option("", "--kernel-rpm-path", type="string",
                      dest="kernel_rpm_path", default=None,
                      help="Path of kernel rpm package, if it was saved in local filesystem.")
    @cmdln.option("", "--bootimg-only", action="store_true", dest="bootimg_only",
                      help="Create boot image only.")

    @cmdln.option("-s", "--skip-compression", action="store_true", dest="skip_compression",
                      default=False, help=_optparse.SUPPRESS_HELP)
    @cmdln.option("", "--skip-minimize", action="store_true", dest="skip_minimize",
                      default=False, help=_optparse.SUPPRESS_HELP)
    @cmdln.option("-l", "--shell", action="store_true", dest="give_shell",
                      help=_optparse.SUPPRESS_HELP)
    @cmdln.option('-d', '--debug', action='store_true',
                      help='Output debugging information')
    @cmdln.option('-v', '--verbose', dest='verbose', action='store_true',
                      help='Output verbose information')
    @cmdln.option('', '--logfile', type="string", dest="file",
                      help='Save debug information to FILE')
    @cmdln.option("", "--traceback", action="store_true",
                      default=False, help="Dump call stack")
    @cmdln.option("", "--save-kernel", action="store_true",
                      dest="save_kernel", default=False,
                      help="Save kernel image file into outdir")
    def do_create(self, subcmd, opts, *args):
        """${cmd_name}: Create an image

        This command is used to create various images, including
        live CD, live USB, loop, raw/KVM/QEMU, VMWare/vmdk,
        VirtualBox/vdi, MooreStone/mrstnand, N8x0/jffs2 and N900/ubi.

        Examples:
           mic create                         # create an image according to the default config
           mic create --format=liveusb        # create a live USB image

        ${cmd_usage}
        ${cmd_option_list}
        """

        self.run_subcmd(subcmd, opts, args)


    """ For mic-image-convertor """
    @cmdln.alias('cv')
    @cmdln.option("-F", "--source-format", type="string", dest="srcformat",
                    help="Source image format, possible values are: raw, vmdk or vdi (default: automatically detect image type).")
    @cmdln.option("-I", "--source-image", type="string", dest="srcimg",
                    help="Source image which was created by mic-image-creator or an image file system.")
    @cmdln.option("-T", "--target-format", type="string", dest="dstformat",
                    help="Target image format, possible values are: livecd and liveusb")
    @cmdln.option("-t", "--tmpdir", type="string",
                      dest="tmpdir", default="/var/tmp",
                      help="Temporary directory to use (default: /var/tmp)")
    @cmdln.option("-o", "--outdir", type="string",
                      dest="outdir", default=None,
                      help="Output directory to use (default: current work dir)")
    @cmdln.option("-P", "--prefix", type="string",
                      dest="prefix", default=None,
                      help="Image name prefix (default: meego)")
    @cmdln.option("-S", "--suffix", type="string",
                      dest="suffix", default=None,
                      help="Image name suffix (default: date stamp)")
    @cmdln.option("-i", "--interactive", action="store_true",
                      dest="interactive", default=False,
                      help="Directly write into a USB disk.")
    @cmdln.option("", "--fstype", type="string",
                      dest="fstype", default="vfat",
                      help="File system type for live USB image, ext3 or vfat, the default is vfat.")
    @cmdln.option("", "--overlay-size-mb", type="int",
                      dest="overlaysizemb", default=64,
                      help="Overlay size in MB as unit, it means how size changes you can save in your live USB disk.")
    @cmdln.option("-s", "--skip-compression", action="store_true", dest="skip_compression",
                      default=False, help=_optparse.SUPPRESS_HELP)
    @cmdln.option("", "--skip-minimize", action="store_true", dest="skip_minimize",
                      default=False, help=_optparse.SUPPRESS_HELP)
    @cmdln.option("-l", "--shell", action="store_true", dest="give_shell",
                      help=_optparse.SUPPRESS_HELP)
    def do_convert(self, subcmd, opts, *args):
        """${cmd_name}: convert an image format to another one

        This command is used to convert a live, raw, vmdk or vdi
        image to a live image.

        Examples:
           mic convert -I <yourimage> -T liveusb    # convert your image to a live USB image

        ${cmd_usage}
        ${cmd_option_list}
        """

        self.run_subcmd(subcmd, opts, args)



    """ For mic-chroot """
    @cmdln.alias('ch')
    @cmdln.option("-s", "--save-to", type="string", dest="saveto",
                    help="Save unpacked filesystem to the specified path ")
    @cmdln.option("", "--unpack-only", action="store_true",
                      dest="unpackonly", default=False,
                      help="Just unpack an image, this is used to"
                           "unpack an image with -s option together"
                     )
    @cmdln.option("-b", "--bind-mounts", type="string", dest="bindmounts",
                      help="Specify bind mount list, for example: -b "
                           "\"/proc:/proc;/:/parentroot\""
                     )
    @cmdln.option("-c", "--convert-to", type="string", dest="convertto",
                      help="Convert it to the specified type live image on"
                           " exiting, the allowed value is livecd or liveusb"
                     )
    @cmdln.option("-e", "--execute", type="string", dest="execute",
                      help="Execute the given command within the chroot"
                           " instead of an interactive shell"
                     )
    @cmdln.option("", "--convert-only", action="store_true",
                      dest="convertonly", default=False,
                      help="Just convert an image, this will skip chroot and"
                           " directly convert an image/filesytem with -c "
                           "option together"
                     )
    @cmdln.option("-o", "--outdir", type="string",
                      dest="outdir", default=None,
                      help="Output directory to use "
                           "(default: current work dir)"
                     )
    @cmdln.option('-d', '--debug', action='store_true',
                      help='Output debugging information')
    @cmdln.option('-v', '--verbose', dest='verbose', action='store_true',
                      help='Output verbose information')
    @cmdln.option('', '--logfile', type="string", dest="file",
                      help='Save debug information to FILE')
    def do_chroot(self, subcmd, opts, *args):
        """${cmd_name}: chroot into an image

        This command is used to chroot into a live image to do some changes.

        Examples:
           mic chroot -s /fs/path <your live image>   # unpack your live image to /fs/path and chroot into it

        ${cmd_usage}
        ${cmd_option_list}
        """

        self.run_subcmd(subcmd, opts, args)


    """ For mic-image-writer """
    @cmdln.alias('wr')
    @cmdln.option("-c", "--console", action="store_true", dest="console",
                      default=False, help="Run in console mode")
    @cmdln.option("-g", "--gui", action="store_true", dest="gui",
                      default=False, help="Run in GUI mode")
    def do_write(self, subcmd, opts, *args):
        """${cmd_name}: write a live image to usb disk

        This command is used to write a live image to usb disk.

        Examples:
           mic write <your live image>   # write a live image to usb disk

        ${cmd_usage}
        ${cmd_option_list}
        """

        self.run_subcmd(subcmd, opts, args)

    """ For mic-vm-launcher """
    @cmdln.alias('lv')
    def do_launchvm(self, subcmd, opts, *args):
        """${cmd_name}: launch a virtual machine image

        This command is used to launch a virtual machine image.

        Examples:
           mic launch <your vm image>   # launch a virtual machine image

        ${cmd_usage}
        ${cmd_option_list}
        """

        self.run_subcmd(subcmd, opts, args)


if __name__ == "__main__":
    mic = MIC()
    sys.exit(mic.main(sys.argv))
