#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function

import argparse
import json
import os
import sys

import kobo.conf
import six

here = sys.path[0]
if here != '/usr/bin':
    # Git checkout
    sys.path[0] = os.path.dirname(here)

import pungi.checks
import pungi.compose
import pungi.paths
import pungi.phases
import pungi.wrappers.scm
import pungi.util
from pungi.wrappers.variants import VariantsXmlParser, VariantsValidationError


class ValidationCompose(pungi.compose.Compose):
    def __init__(self, conf, has_old, topdir):
        self.topdir = topdir
        self.conf = conf
        self._logger = None
        self.just_phases = []
        self.skip_phases = []
        self.has_old_composes = has_old
        self.paths = pungi.paths.Paths(self)
        self.variants = {}

    @property
    def old_composes(self):
        return '/dummy' if self.has_old_composes else None

    @property
    def compose_id(self):
        return 'Dummy-1.0-20160811.t.0'

    @property
    def compose_type(self):
        return 'test'

    @property
    def compose_date(self):
        return '20160811'

    @property
    def compose_respin(self):
        return '0'


def read_variants(compose, config):
    with pungi.util.temp_dir() as tmp_dir:
        scm_dict = compose.conf["variants_file"]
        if isinstance(scm_dict, six.string_types) and scm_dict[0] != '/':
            config_dir = os.path.dirname(config)
            scm_dict = os.path.join(config_dir, scm_dict)
        files = pungi.wrappers.scm.get_file_from_scm(scm_dict, tmp_dir)
        tree_arches = compose.conf.get("tree_arches")
        tree_variants = compose.conf.get("tree_variants")
        with open(os.path.join(tmp_dir, files[0]), "r") as file_obj:
            parser = VariantsXmlParser(file_obj, tree_arches, tree_variants)
            compose.variants = parser.parse()

    compose.all_variants = {}
    for variant in compose.variants.values():
        compose.all_variants[variant.uid] = variant
        for child in variant.get_variants():
            compose.all_variants[child.uid] = child


def run(config, topdir, has_old):
    conf = kobo.conf.PyConfigParser()
    conf.load_from_file(config)

    errors, warnings = pungi.checks.validate(conf)
    if errors or warnings:
        for error in errors + warnings:
            print(error)
        sys.exit(1)

    errors = []
    compose = ValidationCompose(conf, has_old, topdir)
    try:
        read_variants(compose, config)
    except VariantsValidationError as exc:
        errors.extend(str(exc).splitlines())
    except:
        # Failed to read variants, no big deal.
        pass

    pkgset_phase = pungi.phases.PkgsetPhase(compose)
    buildinstall_phase = pungi.phases.BuildinstallPhase(compose)
    phases = [
        pungi.phases.InitPhase(compose),
        buildinstall_phase,
        pkgset_phase,
        pungi.phases.GatherPhase(compose, pkgset_phase),
        pungi.phases.ExtraFilesPhase(compose, pkgset_phase),
        pungi.phases.CreaterepoPhase(compose),
        pungi.phases.OstreeInstallerPhase(compose, buildinstall_phase),
        pungi.phases.OSTreePhase(compose),
        pungi.phases.ProductimgPhase(compose, pkgset_phase),
        pungi.phases.CreateisoPhase(compose, buildinstall_phase),
        pungi.phases.ExtraIsosPhase(compose),
        pungi.phases.LiveImagesPhase(compose),
        pungi.phases.LiveMediaPhase(compose),
        pungi.phases.ImageBuildPhase(compose),
        pungi.phases.ImageChecksumPhase(compose),
        pungi.phases.TestPhase(compose),
    ]

    for phase in phases:
        if phase.skip():
            continue
        try:
            phase.validate()
        except ValueError as ex:
            for i in str(ex).splitlines():
                errors.append("%s: %s" % (phase.name.upper(), i))

    return errors


class DumpSchemaAction(argparse.Action):
    def __call__(self, parser, ns, values, option_string=None):
        json.dump(pungi.checks.make_schema(), sys.stdout,
                  sort_keys=True, indent=4)
        print('')
        sys.exit(0)


def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('--dump-schema', nargs=0, action=DumpSchemaAction,
                        help='print JSON Schema of configuration and exit')
    parser.add_argument('config', metavar='CONFIG',
                        help='configuration file to validate')
    parser.add_argument('--old-composes', action='store_true',
                        help='indicate if pungi-koji will be run with --old-composes option')
    opts = parser.parse_args(args)

    with pungi.util.temp_dir() as topdir:
        errors = run(opts.config, topdir, opts.old_composes)

    for msg in errors:
        print(msg)

    return bool(errors)


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