#!/usr/bin/env python
# Copyright 2015 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.


import argparse
import logging
import os
import subprocess
import sys
import yaml

logger = logging.getLogger(__name__)
env = os.environ.copy()


# YAML FILE FORMAT
# disk_images:
#   -
#      imagename: overcloud-compute
#      arch: amd64
#      type: qcow2
#      elements:
#        - overcloud-compute
#      packages:
#        - vim
#      options:
def parse_opts(argv):
    parser = argparse.ArgumentParser(
        description='Create a set of disk images using a YAML/JSON config file'
                    ' format.')
    parser.add_argument('-c', '--config-file', metavar='CONFIG_FILE',
                        help="""path to the configuration file.""",
                        default='disk_images.yaml')
    parser.add_argument('-o', '--output-directory', metavar='DIRECTORY',
                        help="""output directory for images. """
                             """Defaults to $TRIPLEO_ROOT""",
                        default=env.get('TRIPLEO_ROOT'))
    parser.add_argument('-s', '--skip', action='store_true',
                        help="""skip build if cached image exists. """
                             """Or set USE_CACHE ENV variable to 1.""",
                        default=False)
    parser.add_argument('-d', '--debug', dest="debug", action='store_true',
                        help="Print debugging output.", required=False)
    parser.add_argument('-v', '--verbose', dest="verbose",
                        action='store_true', help="Print verbose output.",
                        required=False)

    opts = parser.parse_args(argv[1:])

    return opts


def configure_logger(verbose=False, debug=False):
    LOG_FORMAT = '[%(asctime)s] [%(levelname)s] %(message)s'
    DATE_FORMAT = '%Y/%m/%d %I:%M:%S %p'
    log_level = logging.WARN

    if debug:
        log_level = logging.DEBUG
    elif verbose:
        log_level = logging.INFO

    logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT,
                        level=log_level)


def main(argv=sys.argv):
    opts = parse_opts(argv)
    configure_logger(opts.verbose, opts.debug)
    logger.info('Using config file at: %s' % opts.config_file)

    if os.path.exists(opts.config_file):
        with open(opts.config_file) as cf:
            disk_images = yaml.load(cf.read()).get("disk_images")
            logger.debug('disk_images JSON: %s' % str(disk_images))
    else:
        logger.error('No config file exists at: %s' % opts.config_file)
        return 1

    if not opts.output_directory:
        logger.error('Please specify --output-directory.')
        return 1

    for image in disk_images:
        arch = image.get('arch', 'amd64')
        img_type = image.get('type', 'qcow2')
        skip_base = image.get('skip_base', 'false')
        docker_target = image.get('docker_target')
        imagename = image.get('imagename')
        logger.info('imagename: %s' % imagename)
        image_path = '%s/%s.%s' % (opts.output_directory, imagename, img_type)
        if opts.skip or env.get('USE_CACHE', '0') == '1':
            logger.info('looking for image at path: %s' % image_path)
            if os.path.exists(image_path):
                logger.warn('Image file exists for image name: %s' % imagename)
                logger.warn('Skipping image build')
                continue
        elements = image.get('elements', [])
        options = image.get('options', [])
        packages = image.get('packages', [])
        cmd = ['disk-image-create', '-a', arch, '-o', image_path, '-t',
               img_type]

        if packages:
            cmd.append('-p')
            cmd.append(','.join(packages))

        if docker_target:
            cmd.append('--docker-target')
            cmd.append(docker_target)

        if skip_base == True:
            cmd.append('-n')

        if options:
            cmd.extend(options)

        # NODE_DIST provides a distro specific element hook
        node_dist = image.get('distro') or env.get('NODE_DIST')
        if node_dist:
            cmd.append(node_dist)

        cmd.extend(elements)

        logger.info('Running %s' % cmd)
        retval = subprocess.call(cmd)
        if retval != 0:
            logger.error('Failed to build image: %s' % imagename)
            return 1

if __name__ == '__main__':
    sys.exit(main(sys.argv))
