#!python

from __future__ import print_function

import pprint
from sys import argv

from os import environ, unlink
from os.path import dirname
import subprocess

from constrictor.configuration import (
    COMMANDS_KEY,
    interpolate_list,
    IGNORE_PATHS_KEY,
    DEB_CONSTRICTOR_KEY,
    DIRECTORIES_KEY,
    LINKS_KEY,
    EXTRA_CONTROL_FIELDS_KEY,
    MAINTAINER_SCRIPTS_KEY,
    CONFIG_FILES_KEY,
)
from constrictor.dpkg import DPKGBuilder
from constrictor.control import BinaryControl
from constrictor.configreader import ConfigReader

DEFAULT_CONFIG_PATH = "./build-config.json"
DEFAULT_OUTPUT_DIRECTORY = "./build"
WORKING_DIR_KEY = "DEB_CONSTRICTOR_WORKING_DIR"
OUTPUT_PATH_KEY = "DEB_CONSTRICTOR_OUTPUT_PATH"


def run_build_command(configuration, command_and_arguments):
    environ.update(configuration.environment_variables)

    interpolate_list(command_and_arguments, configuration.get_template_context())
    # set any environment variables that might now have been computed
    return_code = subprocess.call(command_and_arguments, shell=True)

    if return_code != 0:
        raise subprocess.CalledProcessError(return_code, command_and_arguments)


def run_pre_build_command(config_file_directory, configuration, command_and_arguments):
    environ[WORKING_DIR_KEY] = config_file_directory
    run_build_command(configuration, command_and_arguments)


def run_post_build_command(
    config_file_directory, output_path, configuration, command_and_arguments
):
    environ[WORKING_DIR_KEY] = config_file_directory
    environ[OUTPUT_PATH_KEY] = output_path
    run_build_command(configuration, command_and_arguments)


def get_build_command(constrictor_options, command_name):
    return constrictor_options.get(COMMANDS_KEY, {}).get(command_name)


def build_package(build_config_path, print_output_path, print_computed_config):
    config = ConfigReader(build_config_path).get_configuration()

    if print_computed_config:
        pprint.pprint(config.configuration)
        return

    output_directory = DEFAULT_OUTPUT_DIRECTORY

    control = BinaryControl(
        config["package"],
        config["version"],
        config["architecture"],
        config["maintainer"],
        config["description"],
    )

    control.set_control_fields(config.get(EXTRA_CONTROL_FIELDS_KEY, {}))

    deb_constrictor_options = config.get(DEB_CONSTRICTOR_KEY, {})

    pre_build_command = get_build_command(deb_constrictor_options, "prebuild")

    config_file_directory = dirname(build_config_path)

    if pre_build_command:
        run_pre_build_command(config_file_directory, config, pre_build_command)

    d = DPKGBuilder(
        output_directory,
        control,
        config.get(DIRECTORIES_KEY),
        config.get(LINKS_KEY),
        config.get(MAINTAINER_SCRIPTS_KEY),
        ignore_paths=deb_constrictor_options.get(IGNORE_PATHS_KEY),
        configuration_files=config.get(CONFIG_FILES_KEY),
    )

    output_path = d.build_package()

    if print_output_path:
        print(output_path)

    post_build_command = get_build_command(deb_constrictor_options, "postbuild")

    if post_build_command:
        run_post_build_command(
            config_file_directory, output_path, config, post_build_command
        )

    if deb_constrictor_options.get("remove_after_build") is True:
        unlink(output_path)


def main():
    args = argv

    if "-p" in args:
        print_output_path = True
        args.remove("-p")
    else:
        print_output_path = False

    if "-c" in args:
        # print computed output and exit
        print_computed_config = True
        args.remove("-c")
    else:
        print_computed_config = False

    build_package(
        args[1] if len(argv) > 1 else DEFAULT_CONFIG_PATH,
        print_output_path,
        print_computed_config,
    )


if __name__ == "__main__":
    main()
